Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp
Warning:line 7513, 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-19/lib/clang/19 -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 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-19/lib/clang/19/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-2024-09-22-115206-3586786-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*);
224
225// Returns true if aFrame is an anonymous flex/grid item.
226static inline bool IsAnonymousItem(const nsIFrame* aFrame) {
227 return aFrame->Style()->GetPseudoType() == PseudoStyleType::anonymousItem;
228}
229
230// Returns true IFF the given nsIFrame is a nsFlexContainerFrame and represents
231// a -webkit-{inline-}box container.
232static inline bool IsFlexContainerForLegacyWebKitBox(const nsIFrame* aFrame) {
233 return aFrame->IsFlexContainerFrame() &&
234 aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_WEBKIT_BOX);
235}
236
237#if DEBUG1
238static void AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
239 const nsIFrame* aParent) {
240 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"
, 240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsAnonymousItem(aChild)"
") (" "expected an anonymous item child frame" ")"); do { *(
(volatile int*)__null) = 240; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
241 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"
, 241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ") ("
"expected a parent frame" ")"); do { *((volatile int*)__null
) = 241; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
242 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"
, 244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 244
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
243 "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"
, 244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 244
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
244 "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"
, 244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 244
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
245}
246#else
247# define AssertAnonymousFlexOrGridItemParent(x, y) PR_BEGIN_MACROdo { PR_END_MACRO} while (0)
248#endif
249
250#define ToCreationFunc(_func)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
_func(aPs, aStyle); }
\
251 [](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { \
252 return _func(aPs, aStyle); \
253 }
254
255/**
256 * True if aFrame is an actual inline frame in the sense of non-replaced
257 * display:inline CSS boxes. In other words, it can be affected by {ib}
258 * splitting and can contain first-letter frames. Basically, this is either an
259 * inline frame (positioned or otherwise) or an line frame (this last because
260 * it can contain first-letter and because inserting blocks in the middle of it
261 * needs to terminate it).
262 */
263static bool IsInlineFrame(const nsIFrame* aFrame) {
264 return aFrame->IsLineParticipant();
265}
266
267/**
268 * True for display: contents elements.
269 */
270static inline bool IsDisplayContents(const Element* aElement) {
271 return aElement->IsDisplayContents();
272}
273
274static inline bool IsDisplayContents(const nsIContent* aContent) {
275 return aContent->IsElement() && IsDisplayContents(aContent->AsElement());
276}
277
278/**
279 * True if aFrame is an instance of an SVG frame class or is an inline/block
280 * frame being used for SVG text.
281 */
282static bool IsFrameForSVG(const nsIFrame* aFrame) {
283 return aFrame->IsSVGFrame() || aFrame->IsInSVGTextSubtree();
284}
285
286static bool IsLastContinuationForColumnContent(const nsIFrame* aFrame) {
287 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"
, 287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ")")
; do { *((volatile int*)__null) = 287; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
288 return aFrame->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
289 !aFrame->GetNextContinuation();
290}
291
292/**
293 * Returns true iff aFrame explicitly prevents its descendants from floating
294 * (at least, down to the level of descendants which themselves are
295 * float-containing blocks -- those will manage the floating status of any
296 * lower-level descendents inside them, of course).
297 */
298static bool ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame) {
299 return aFrame->IsFlexOrGridContainer() || aFrame->IsMathMLFrame();
300}
301
302// Return true if column-span descendants should be suppressed under aFrame's
303// subtree (until a multi-column container re-establishing a block formatting
304// context). Basically, this is testing whether aFrame establishes a new block
305// formatting context or not.
306static bool ShouldSuppressColumnSpanDescendants(nsIFrame* aFrame) {
307 if (aFrame->Style()->GetPseudoType() == PseudoStyleType::columnContent) {
308 // Never suppress column-span under ::-moz-column-content frames.
309 return false;
310 }
311
312 if (aFrame->IsInlineFrame()) {
313 // Allow inline frames to have column-span block children.
314 return false;
315 }
316
317 if (!aFrame->IsBlockFrameOrSubclass() ||
318 aFrame->HasAnyStateBits(NS_BLOCK_BFC | NS_FRAME_OUT_OF_FLOW) ||
319 aFrame->IsFixedPosContainingBlock()) {
320 // Need to suppress column-span if we:
321 // - Are a different block formatting context,
322 // - Are an out-of-flow frame, OR
323 // - Establish a containing block for fixed-position descendants
324 //
325 // For example, the children of a column-span never need to be further
326 // processed even if there is a nested column-span child. Because a
327 // column-span always creates its own block formatting context, a nested
328 // column-span child won't be in the same block formatting context with the
329 // nearest multi-column ancestor. This is the same case as if the
330 // column-span is outside of a multi-column hierarchy.
331 return true;
332 }
333
334 return false;
335}
336
337// Reparent a frame into a wrapper frame that is a child of its old parent.
338static void ReparentFrame(RestyleManager* aRestyleManager,
339 nsContainerFrame* aNewParentFrame, nsIFrame* aFrame,
340 bool aForceStyleReparent) {
341 aFrame->SetParent(aNewParentFrame);
342 // We reparent frames for two reasons: to put them inside ::first-line, and to
343 // put them inside some wrapper anonymous boxes.
344 if (aForceStyleReparent) {
345 aRestyleManager->ReparentComputedStyleForFirstLine(aFrame);
346 }
347}
348
349static void ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
350 nsContainerFrame* aNewParentFrame,
351 const nsFrameList& aFrameList,
352 bool aForceStyleReparent) {
353 RestyleManager* restyleManager = aFrameConstructor->RestyleManager();
354 for (nsIFrame* f : aFrameList) {
355 ReparentFrame(restyleManager, aNewParentFrame, f, aForceStyleReparent);
356 }
357}
358
359//----------------------------------------------------------------------
360//
361// When inline frames get weird and have block frames in them, we
362// annotate them to help us respond to incremental content changes
363// more easily.
364
365static inline bool IsFramePartOfIBSplit(nsIFrame* aFrame) {
366 bool result = aFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT);
367 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"
, 369); 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) = 369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
368 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"
, 369); 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) = 369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
369 "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"
, 369); 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) = 369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
370 return result;
371}
372
373static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame) {
374 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"
, 374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "Shouldn't call this" ")"); do { *((volatile int*)__null
) = 374; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
375
376 // We only store the "ib-split sibling" annotation with the first
377 // frame in the continuation chain. Walk back to find that frame now.
378 return aFrame->FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
379}
380
381static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame) {
382 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"
, 382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "Shouldn't call this" ")"); do { *((volatile int*)__null
) = 382; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
383
384 // We only store the ib-split sibling annotation with the first
385 // frame in the continuation chain. Walk back to find that frame now.
386 return aFrame->FirstContinuation()->GetProperty(
387 nsIFrame::IBSplitPrevSibling());
388}
389
390static nsContainerFrame* GetLastIBSplitSibling(nsIFrame* aFrame) {
391 for (nsIFrame *frame = aFrame, *next;; frame = next) {
392 next = GetIBSplitSibling(frame);
393 if (!next) {
394 return static_cast<nsContainerFrame*>(frame);
395 }
396 }
397 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"
, 397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unreachable code" ")"); do { *((
volatile int*)__null) = 397; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
398 return nullptr;
399}
400
401static void SetFrameIsIBSplit(nsContainerFrame* aFrame,
402 nsContainerFrame* aIBSplitSibling) {
403 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"
, 403); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"bad args!" ")"); do { *((volatile int*)__null) = 403; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
404
405 // We should be the only continuation
406 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"
, 407); MOZ_PretendNoReturn(); } } while (0)
407 "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"
, 407); MOZ_PretendNoReturn(); } } while (0)
;
408 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"
, 410); MOZ_PretendNoReturn(); } } while (0)
409 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"
, 410); MOZ_PretendNoReturn(); } } while (0)
410 "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"
, 410); MOZ_PretendNoReturn(); } } while (0)
;
411
412 // Mark the frame as ib-split.
413 aFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
414
415 if (aIBSplitSibling) {
416 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"
, 418); MOZ_PretendNoReturn(); } } while (0)
417 "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"
, 418); MOZ_PretendNoReturn(); } } while (0)
418 "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"
, 418); MOZ_PretendNoReturn(); } } while (0)
;
419
420 // Store the ib-split sibling (if we were given one) with the
421 // first frame in the flow.
422 aFrame->SetProperty(nsIFrame::IBSplitSibling(), aIBSplitSibling);
423 aIBSplitSibling->SetProperty(nsIFrame::IBSplitPrevSibling(), aFrame);
424 }
425}
426
427static nsIFrame* GetIBContainingBlockFor(nsIFrame* aFrame) {
428 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"
, 430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
429 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"
, 430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
430 "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"
, 430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
431
432 // Get the first "normal" ancestor of the target frame.
433 nsIFrame* parentFrame;
434 do {
435 parentFrame = aFrame->GetParent();
436
437 if (!parentFrame) {
438 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"
, 438); MOZ_PretendNoReturn(); } while (0)
;
439 return aFrame;
440 }
441
442 // Note that we ignore non-ib-split frames which have a pseudo on their
443 // ComputedStyle -- they're not the frames we're looking for! In
444 // particular, they may be hiding a real parent that _is_ in an ib-split.
445 if (!IsFramePartOfIBSplit(parentFrame) &&
446 !parentFrame->Style()->IsPseudoOrAnonBox()) {
447 break;
448 }
449
450 aFrame = parentFrame;
451 } while (true);
452
453 // post-conditions
454 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"
, 456); MOZ_PretendNoReturn(); } } while (0)
455 "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"
, 456); MOZ_PretendNoReturn(); } } while (0)
456 "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"
, 456); MOZ_PretendNoReturn(); } } while (0)
;
457 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"
, 458); MOZ_PretendNoReturn(); } } while (0)
458 "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"
, 458); MOZ_PretendNoReturn(); } } while (0)
;
459
460 return parentFrame;
461}
462
463// Find the multicol containing block suitable for reframing.
464//
465// Note: this function may not return a ColumnSetWrapperFrame. For example, if
466// the multicol containing block has "overflow:scroll" style,
467// ScrollContainerFrame is returned because ColumnSetWrapperFrame is the
468// scrolled frame which has the -moz-scrolled-content pseudo style. We may walk
469// up "too far", but in terms of correctness of reframing, it's OK.
470static nsContainerFrame* GetMultiColumnContainingBlockFor(nsIFrame* aFrame) {
471 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"
, 472); 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) = 472; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
472 "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"
, 472); 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) = 472; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
473
474 nsContainerFrame* current = aFrame->GetParent();
475 while (current &&
476 (current->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) ||
477 current->Style()->IsPseudoOrAnonBox())) {
478 current = current->GetParent();
479 }
480
481 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"
, 482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "current" ") ("
"No multicol containing block in a valid column hierarchy?" ")"
); do { *((volatile int*)__null) = 482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
482 "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"
, 482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "current" ") ("
"No multicol containing block in a valid column hierarchy?" ")"
); do { *((volatile int*)__null) = 482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
483
484 return current;
485}
486
487static bool InsertSeparatorBeforeAccessKey() {
488 static bool sInitialized = false;
489 static bool sValue = false;
490 if (!sInitialized) {
491 sInitialized = true;
492
493 const char* prefName = "intl.menuitems.insertseparatorbeforeaccesskeys";
494 nsAutoString val;
495 Preferences::GetLocalizedString(prefName, val);
496 sValue = val.EqualsLiteral("true");
497 }
498 return sValue;
499}
500
501static bool AlwaysAppendAccessKey() {
502 static bool sInitialized = false;
503 static bool sValue = false;
504 if (!sInitialized) {
505 sInitialized = true;
506 const char* prefName = "intl.menuitems.alwaysappendaccesskeys";
507 nsAutoString val;
508 Preferences::GetLocalizedString(prefName, val);
509 sValue = val.EqualsLiteral("true");
510 }
511 return sValue;
512}
513
514//----------------------------------------------------------------------
515
516// Block/inline frame construction logic. We maintain a few invariants here:
517//
518// 1. Block frames contain block and inline frames.
519//
520// 2. Inline frames only contain inline frames. If an inline parent has a block
521// child then the block child is migrated upward until it lands in a block
522// parent (the inline frames containing block is where it will end up).
523
524inline void SetInitialSingleChild(nsContainerFrame* aParent, nsIFrame* aFrame) {
525 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"
, 525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->GetNextSibling()"
") (" "Should be using a frame list" ")"); do { *((volatile int
*)__null) = 525; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
526 aParent->SetInitialChildList(FrameChildListID::Principal,
527 nsFrameList(aFrame, aFrame));
528}
529
530// -----------------------------------------------------------
531
532// Structure used when constructing formatting object trees. Contains
533// state information needed for absolutely positioned elements
534namespace mozilla {
535struct AbsoluteFrameList final : public nsFrameList {
536 // Containing block for absolutely positioned elements.
537 nsContainerFrame* mContainingBlock;
538
539 explicit AbsoluteFrameList(nsContainerFrame* aContainingBlock = nullptr)
540 : mContainingBlock(aContainingBlock) {}
541
542 // Transfer frames in aOther to this list. aOther becomes empty after this
543 // operation.
544 AbsoluteFrameList(AbsoluteFrameList&& aOther) = default;
545 AbsoluteFrameList& operator=(AbsoluteFrameList&& aOther) = default;
546
547#ifdef DEBUG1
548 // XXXbz Does this need a debug-only assignment operator that nulls out the
549 // childList in the AbsoluteFrameList we're copying? Introducing a difference
550 // between debug and non-debug behavior seems bad, so I guess not...
551 ~AbsoluteFrameList() {
552 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"
, 553); MOZ_PretendNoReturn(); } } while (0)
553 "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"
, 553); MOZ_PretendNoReturn(); } } while (0)
;
554 }
555#endif
556};
557} // namespace mozilla
558
559// -----------------------------------------------------------
560
561// Structure for saving the existing state when pushing/poping containing
562// blocks. The destructor restores the state to its previous state
563class MOZ_STACK_CLASS nsFrameConstructorSaveState {
564 public:
565 ~nsFrameConstructorSaveState();
566
567 private:
568 // Pointer to struct whose data we save/restore.
569 AbsoluteFrameList* mList = nullptr;
570
571 // The saved pointer to the fixed list.
572 AbsoluteFrameList* mSavedFixedList = nullptr;
573
574 // Copy of original frame list. This can be the original absolute list or a
575 // float list.
576 AbsoluteFrameList mSavedList;
577
578 // The name of the child list in which our frames would belong.
579 mozilla::FrameChildListID mChildListID = FrameChildListID::Principal;
580 nsFrameConstructorState* mState = nullptr;
581
582 friend class nsFrameConstructorState;
583};
584
585// Structure used for maintaining state information during the
586// frame construction process
587class MOZ_STACK_CLASS nsFrameConstructorState {
588 public:
589 nsPresContext* mPresContext;
590 PresShell* mPresShell;
591 nsCSSFrameConstructor* mFrameConstructor;
592
593 // Containing block information for out-of-flow frames.
594 //
595 // Floats are easy. Whatever is our float CB.
596 //
597 // Regular abspos elements are easy too. Its containing block can be the
598 // nearest abspos element, or the ICB (the canvas frame).
599 //
600 // Top layer abspos elements are always children of the ICB, but we can get
601 // away with having two different lists (mAbsoluteList and
602 // mTopLayerAbsoluteList), because because top layer frames cause
603 // non-top-layer frames to be contained inside (so any descendants of a top
604 // layer abspos can never share containing block with it, unless they're also
605 // in the top layer).
606 //
607 // Regular fixed elements however are trickier. Fixed elements can be
608 // contained in one of three lists:
609 //
610 // * mAbsoluteList, if our abspos cb is also a fixpos cb (e.g., is
611 // transformed or has a filter).
612 //
613 // * mAncestorFixedList, if the fixpos cb is an ancestor element other than
614 // the viewport frame, (so, a transformed / filtered
615 // ancestor).
616 //
617 // * mRealFixedList, which is also the fixed list used for the top layer
618 // fixed items, which is the fixed list of the viewport
619 // frame.
620 //
621 // It is important that mRealFixedList is shared between regular and top layer
622 // fixpos elements, since no-top-layer descendants of top layer fixed elements
623 // could share ICB and vice versa, so without that there would be no guarantee
624 // of layout ordering between them.
625 AbsoluteFrameList mFloatedList;
626 AbsoluteFrameList mAbsoluteList;
627 AbsoluteFrameList mTopLayerAbsoluteList;
628 AbsoluteFrameList mAncestorFixedList;
629 AbsoluteFrameList mRealFixedList;
630
631 // Never null, always pointing to one of the lists documented above.
632 AbsoluteFrameList* mFixedList;
633
634 // What `page: auto` resolves to. This is the used page-name of the parent
635 // frame. Updated by AutoFrameConstructionPageName.
636 const nsAtom* mAutoPageNameValue = nullptr;
637
638 nsCOMPtr<nsILayoutHistoryState> mFrameState;
639 // These bits will be added to the state bits of any frame we construct
640 // using this state.
641 nsFrameState mAdditionalStateBits{0};
642
643 // If false (which is the default) then call SetPrimaryFrame() as needed
644 // during frame construction. If true, don't make any SetPrimaryFrame()
645 // calls, except for generated content which doesn't have a primary frame
646 // yet. The mCreatingExtraFrames == true mode is meant to be used for
647 // construction of random "extra" frames for elements via normal frame
648 // construction APIs (e.g. replication of things across pages in paginated
649 // mode).
650 bool mCreatingExtraFrames;
651
652 // This keeps track of whether we have found a "rendered legend" for
653 // the current FieldSetFrame.
654 bool mHasRenderedLegend;
655
656 nsTArray<RefPtr<nsIContent>> mGeneratedContentWithInitializer;
657
658#ifdef DEBUG1
659 // Record the float containing block candidate passed into
660 // MaybePushFloatContainingBlock() to keep track that we've call the method to
661 // handle the float CB scope before processing the CB's children. It is reset
662 // in ConstructFramesFromItemList().
663 nsContainerFrame* mFloatCBCandidate = nullptr;
664#endif
665
666 // Constructor
667 // Use the passed-in history state.
668 nsFrameConstructorState(
669 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
670 nsContainerFrame* aAbsoluteContainingBlock,
671 nsContainerFrame* aFloatContainingBlock,
672 already_AddRefed<nsILayoutHistoryState> aHistoryState);
673 // Get the history state from the pres context's pres shell.
674 nsFrameConstructorState(PresShell* aPresShell,
675 nsContainerFrame* aFixedContainingBlock,
676 nsContainerFrame* aAbsoluteContainingBlock,
677 nsContainerFrame* aFloatContainingBlock);
678
679 ~nsFrameConstructorState();
680
681 // Process the frame insertions for all the out-of-flow nsAbsoluteItems.
682 void ProcessFrameInsertionsForAllLists();
683
684 // Function to push the existing absolute containing block state and
685 // create a new scope. Code that uses this function should get matching
686 // logic in GetAbsoluteContainingBlock.
687 // Also makes aNewAbsoluteContainingBlock the containing block for
688 // fixed-pos elements if necessary.
689 // aPositionedFrame is the frame whose style actually makes
690 // aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable
691 // element aPositionedFrame is the element's primary frame and
692 // aNewAbsoluteContainingBlock is the scrolled frame.
693 void PushAbsoluteContainingBlock(
694 nsContainerFrame* aNewAbsoluteContainingBlock, nsIFrame* aPositionedFrame,
695 nsFrameConstructorSaveState& aSaveState);
696
697 // Function to forbid floats descendants under aFloatCBCandidate, or open a
698 // new float containing block scope for aFloatCBCandidate. The current
699 // state is saved in aSaveState if a new scope is pushed.
700 void MaybePushFloatContainingBlock(nsContainerFrame* aFloatCBCandidate,
701 nsFrameConstructorSaveState& aSaveState);
702
703 // Helper function for MaybePushFloatContainingBlock().
704 void PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
705 nsFrameConstructorSaveState& aSaveState);
706
707 // Function to return the proper geometric parent for a frame with display
708 // struct given by aStyleDisplay and parent's frame given by
709 // aContentParentFrame.
710 nsContainerFrame* GetGeometricParent(
711 const nsStyleDisplay& aStyleDisplay,
712 nsContainerFrame* aContentParentFrame) const;
713
714 // Collect absolute frames in mAbsoluteList which are proper descendants
715 // of aNewParent, and reparent them to aNewParent.
716 //
717 // Note: This function does something unusual that moves absolute items
718 // after their frames are constructed under a column hierarchy which has
719 // column-span elements. Do not use this if you're not dealing with
720 // columns.
721 void ReparentAbsoluteItems(nsContainerFrame* aNewParent);
722
723 // Collect floats in mFloatedList which are proper descendants of aNewParent,
724 // and reparent them to aNewParent.
725 //
726 // Note: This function does something unusual that moves floats after their
727 // frames are constructed under a column hierarchy which has column-span
728 // elements. Do not use this if you're not dealing with columns.
729 void ReparentFloats(nsContainerFrame* aNewParent);
730
731 /**
732 * Function to add a new frame to the right frame list. This MUST be called
733 * on frames before their children have been processed if the frames might
734 * conceivably be out-of-flow; otherwise cleanup in error cases won't work
735 * right. Also, this MUST be called on frames after they have been
736 * initialized.
737 * @param aNewFrame the frame to add
738 * @param aFrameList the list to add in-flow frames to
739 * @param aContent the content pointer for aNewFrame
740 * @param aParentFrame the parent frame for the content if it were in-flow
741 * @param aCanBePositioned pass false if the frame isn't allowed to be
742 * positioned
743 * @param aCanBeFloated pass false if the frame isn't allowed to be
744 * floated
745 */
746 void AddChild(nsIFrame* aNewFrame, nsFrameList& aFrameList,
747 nsIContent* aContent, nsContainerFrame* aParentFrame,
748 bool aCanBePositioned = true, bool aCanBeFloated = true,
749 bool aInsertAfter = false,
750 nsIFrame* aInsertAfterFrame = nullptr);
751
752 /**
753 * Function to return the fixed-pos element list. Normally this will just
754 * hand back the fixed-pos element list, but in case we're dealing with a
755 * transformed element that's acting as an abs-pos and fixed-pos container,
756 * we'll hand back the abs-pos list. Callers should use this function if they
757 * want to get the list acting as the fixed-pos item parent.
758 */
759 AbsoluteFrameList& GetFixedList() { return *mFixedList; }
760 const AbsoluteFrameList& GetFixedList() const { return *mFixedList; }
761
762 protected:
763 friend class nsFrameConstructorSaveState;
764
765 /**
766 * ProcessFrameInsertions takes the frames in aFrameList and adds them as
767 * kids to the aChildListID child list of |aFrameList.containingBlock|.
768 */
769 void ProcessFrameInsertions(AbsoluteFrameList& aFrameList,
770 mozilla::FrameChildListID aChildListID);
771
772 /**
773 * GetOutOfFlowFrameList selects the out-of-flow frame list the new
774 * frame should be added to. If the frame shouldn't be added to any
775 * out-of-flow list, it returns nullptr. The corresponding type of
776 * placeholder is also returned via the aPlaceholderType parameter
777 * if this method doesn't return nullptr. The caller should check
778 * whether the returned list really has a containing block.
779 */
780 AbsoluteFrameList* GetOutOfFlowFrameList(nsIFrame* aNewFrame,
781 bool aCanBePositioned,
782 bool aCanBeFloated,
783 nsFrameState* aPlaceholderType);
784
785 void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
786};
787
788nsFrameConstructorState::nsFrameConstructorState(
789 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
790 nsContainerFrame* aAbsoluteContainingBlock,
791 nsContainerFrame* aFloatContainingBlock,
792 already_AddRefed<nsILayoutHistoryState> aHistoryState)
793 : mPresContext(aPresShell->GetPresContext()),
794 mPresShell(aPresShell),
795 mFrameConstructor(aPresShell->FrameConstructor()),
796 mFloatedList(aFloatContainingBlock),
797 mAbsoluteList(aAbsoluteContainingBlock),
798 mTopLayerAbsoluteList(mFrameConstructor->GetCanvasFrame()),
799 mAncestorFixedList(aFixedContainingBlock),
800 mRealFixedList(
801 static_cast<nsContainerFrame*>(mFrameConstructor->GetRootFrame())),
802 // See PushAbsoluteContaningBlock below
803 mFrameState(aHistoryState),
804 mCreatingExtraFrames(false),
805 mHasRenderedLegend(false) {
806 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)
;
807 mFixedList = [&] {
808 if (aFixedContainingBlock == aAbsoluteContainingBlock) {
809 return &mAbsoluteList;
810 }
811 if (aAbsoluteContainingBlock == mRealFixedList.mContainingBlock) {
812 return &mRealFixedList;
813 }
814 return &mAncestorFixedList;
815 }();
816}
817
818nsFrameConstructorState::nsFrameConstructorState(
819 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
820 nsContainerFrame* aAbsoluteContainingBlock,
821 nsContainerFrame* aFloatContainingBlock)
822 : nsFrameConstructorState(
823 aPresShell, aFixedContainingBlock, aAbsoluteContainingBlock,
824 aFloatContainingBlock,
825 aPresShell->GetDocument()->GetLayoutHistoryState()) {}
826
827nsFrameConstructorState::~nsFrameConstructorState() {
828 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)
;
829 ProcessFrameInsertionsForAllLists();
830 for (auto& content : Reversed(mGeneratedContentWithInitializer)) {
831 content->RemoveProperty(nsGkAtoms::genConInitializerProperty);
832 }
833}
834
835void nsFrameConstructorState::ProcessFrameInsertionsForAllLists() {
836 ProcessFrameInsertions(mFloatedList, FrameChildListID::Float);
837 ProcessFrameInsertions(mAbsoluteList, FrameChildListID::Absolute);
838 ProcessFrameInsertions(mTopLayerAbsoluteList, FrameChildListID::Absolute);
839 ProcessFrameInsertions(*mFixedList, FrameChildListID::Fixed);
840 ProcessFrameInsertions(mRealFixedList, FrameChildListID::Fixed);
841}
842
843void nsFrameConstructorState::PushAbsoluteContainingBlock(
844 nsContainerFrame* aNewAbsoluteContainingBlock, nsIFrame* aPositionedFrame,
845 nsFrameConstructorSaveState& aSaveState) {
846 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"
, 847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
") (" "We should have both or none" ")"); do { *((volatile int
*)__null) = 847; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
847 "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"
, 847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
") (" "We should have both or none" ")"); do { *((volatile int
*)__null) = 847; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
848 aSaveState.mList = &mAbsoluteList;
849 aSaveState.mChildListID = FrameChildListID::Absolute;
850 aSaveState.mState = this;
851 aSaveState.mSavedList = std::move(mAbsoluteList);
852 aSaveState.mSavedFixedList = mFixedList;
853 mAbsoluteList = AbsoluteFrameList(aNewAbsoluteContainingBlock);
854 mFixedList = [&] {
855 if (!aPositionedFrame || aPositionedFrame->IsFixedPosContainingBlock()) {
856 // See if we need to treat abspos and fixedpos the same. This happens if
857 // we're a transformed/filtered/etc element, or if we force a null abspos
858 // containing block (for mathml for example).
859 return &mAbsoluteList;
860 }
861 if (aPositionedFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Top) {
862 // If our new CB is in the top layer, and isn't a fixed CB itself, we also
863 // escape the usual containment.
864 return &mRealFixedList;
865 }
866 if (mFixedList == &mAbsoluteList) {
867 // If we were pointing to our old absolute list, keep pointing to it.
868 return &aSaveState.mSavedList;
869 }
870 // Otherwise keep pointing to the current thing (another ancestor's
871 // absolute list, or the real fixed list, doesn't matter).
872 return mFixedList;
873 }();
874
875 if (aNewAbsoluteContainingBlock) {
876 aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
877 }
878}
879
880void nsFrameConstructorState::MaybePushFloatContainingBlock(
881 nsContainerFrame* aFloatCBCandidate,
882 nsFrameConstructorSaveState& aSaveState) {
883 // The logic here needs to match the logic in GetFloatContainingBlock().
884 if (ShouldSuppressFloatingOfDescendants(aFloatCBCandidate)) {
885 // Pushing a null float containing block forbids any frames from being
886 // floated until a new float containing block is pushed. See implementation
887 // of nsFrameConstructorState::AddChild().
888 //
889 // XXX we should get rid of null float containing blocks and teach the
890 // various frame classes to deal with floats instead.
891 PushFloatContainingBlock(nullptr, aSaveState);
892 } else if (aFloatCBCandidate->IsFloatContainingBlock()) {
893 PushFloatContainingBlock(aFloatCBCandidate, aSaveState);
894 }
895
896#ifdef DEBUG1
897 mFloatCBCandidate = aFloatCBCandidate;
898#endif
899}
900
901void nsFrameConstructorState::PushFloatContainingBlock(
902 nsContainerFrame* aNewFloatContainingBlock,
903 nsFrameConstructorSaveState& aSaveState) {
904 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"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 906; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
905 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"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 906; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
906 "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"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 906; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
907 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"
, 911); MOZ_PretendNoReturn(); } } while (0)
908 !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"
, 911); MOZ_PretendNoReturn(); } } while (0)
909 !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"
, 911); MOZ_PretendNoReturn(); } } while (0)
910 "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"
, 911); MOZ_PretendNoReturn(); } } while (0)
911 "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"
, 911); MOZ_PretendNoReturn(); } } while (0)
;
912 aSaveState.mList = &mFloatedList;
913 aSaveState.mSavedList = std::move(mFloatedList);
914 aSaveState.mChildListID = FrameChildListID::Float;
915 aSaveState.mState = this;
916 mFloatedList = AbsoluteFrameList(aNewFloatContainingBlock);
917}
918
919nsContainerFrame* nsFrameConstructorState::GetGeometricParent(
920 const nsStyleDisplay& aStyleDisplay,
921 nsContainerFrame* aContentParentFrame) const {
922 // If there is no container for a fixed, absolute, or floating root
923 // frame, we will ignore the positioning. This hack is originally
924 // brought to you by the letter T: tables, since other roots don't
925 // even call into this code. See bug 178855.
926 //
927 // XXX Disabling positioning in this case is a hack. If one was so inclined,
928 // one could support this either by (1) inserting a dummy block between the
929 // table and the canvas or (2) teaching the canvas how to reflow positioned
930 // elements. (1) has the usual problems when multiple frames share the same
931 // content (notice all the special cases in this file dealing with inner
932 // tables and table wrappers which share the same content). (2) requires some
933 // work and possible factoring.
934 //
935 // XXXbz couldn't we just force position to "static" on roots and
936 // float to "none"? That's OK per CSS 2.1, as far as I can tell.
937
938 if (aContentParentFrame && aContentParentFrame->IsInSVGTextSubtree()) {
939 return aContentParentFrame;
940 }
941
942 if (aStyleDisplay.IsFloatingStyle() && mFloatedList.mContainingBlock) {
943 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"
, 944); MOZ_PretendNoReturn(); } } while (0)
944 "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"
, 944); MOZ_PretendNoReturn(); } } while (0)
;
945 return mFloatedList.mContainingBlock;
946 }
947
948 if (aStyleDisplay.mTopLayer != StyleTopLayer::None) {
949 MOZ_ASSERT(aStyleDisplay.mTopLayer == StyleTopLayer::Top,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.mTopLayer == StyleTopLayer::Top)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStyleDisplay.mTopLayer == StyleTopLayer::Top))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aStyleDisplay.mTopLayer == StyleTopLayer::Top"
" (" "-moz-top-layer should be either none or top" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mTopLayer == StyleTopLayer::Top"
") (" "-moz-top-layer should be either none or top" ")"); do
{ *((volatile int*)__null) = 950; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
950 "-moz-top-layer should be either none or top")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.mTopLayer == StyleTopLayer::Top)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStyleDisplay.mTopLayer == StyleTopLayer::Top))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aStyleDisplay.mTopLayer == StyleTopLayer::Top"
" (" "-moz-top-layer should be either none or top" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mTopLayer == StyleTopLayer::Top"
") (" "-moz-top-layer should be either none or top" ")"); do
{ *((volatile int*)__null) = 950; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
951 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"
, 952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.IsAbsolutelyPositionedStyle()"
") (" "Top layer items should always be absolutely positioned"
")"); do { *((volatile int*)__null) = 952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
952 "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"
, 952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.IsAbsolutelyPositionedStyle()"
") (" "Top layer items should always be absolutely positioned"
")"); do { *((volatile int*)__null) = 952; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
953 if (aStyleDisplay.mPosition == StylePositionProperty::Fixed) {
954 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"
, 954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRealFixedList.mContainingBlock"
") (" "No root frame?" ")"); do { *((volatile int*)__null) =
954; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
955 return mRealFixedList.mContainingBlock;
956 }
957 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"
, 957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mPosition == StylePositionProperty::Absolute"
")"); do { *((volatile int*)__null) = 957; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
958 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"
, 958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTopLayerAbsoluteList.mContainingBlock"
")"); do { *((volatile int*)__null) = 958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
959 return mTopLayerAbsoluteList.mContainingBlock;
960 }
961
962 if (aStyleDisplay.mPosition == StylePositionProperty::Absolute &&
963 mAbsoluteList.mContainingBlock) {
964 return mAbsoluteList.mContainingBlock;
965 }
966
967 if (aStyleDisplay.mPosition == StylePositionProperty::Fixed &&
968 mFixedList->mContainingBlock) {
969 return mFixedList->mContainingBlock;
970 }
971
972 return aContentParentFrame;
973}
974
975void nsFrameConstructorState::ReparentAbsoluteItems(
976 nsContainerFrame* aNewParent) {
977 // Bug 1491727: This function might not conform to the spec. See
978 // https://github.com/w3c/csswg-drafts/issues/1894.
979
980 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"
, 981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 981; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
981 "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"
, 981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 981; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
982
983 AbsoluteFrameList newAbsoluteItems(aNewParent);
984
985 nsIFrame* current = mAbsoluteList.FirstChild();
986 while (current) {
987 nsIFrame* placeholder = current->GetPlaceholderFrame();
988
989 if (nsLayoutUtils::IsProperAncestorFrame(aNewParent, placeholder)) {
990 nsIFrame* next = current->GetNextSibling();
991 mAbsoluteList.RemoveFrame(current);
992 newAbsoluteItems.AppendFrame(aNewParent, current);
993 current = next;
994 } else {
995 current = current->GetNextSibling();
996 }
997 }
998
999 if (newAbsoluteItems.NotEmpty()) {
1000 // ~nsFrameConstructorSaveState() will move newAbsoluteItems to
1001 // aNewParent's absolute child list.
1002 nsFrameConstructorSaveState absoluteSaveState;
1003
1004 // It doesn't matter whether aNewParent has position style or not. Caller
1005 // won't call us if we can't have absolute children.
1006 PushAbsoluteContainingBlock(aNewParent, aNewParent, absoluteSaveState);
1007 mAbsoluteList = std::move(newAbsoluteItems);
1008 }
1009}
1010
1011void nsFrameConstructorState::ReparentFloats(nsContainerFrame* aNewParent) {
1012 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"
, 1013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 1013; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1013 "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"
, 1013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 1013; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1014 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"
, 1016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1016; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1015 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"
, 1016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1016; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1016 "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"
, 1016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1016; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1017
1018 // Gather floats that should reparent under aNewParent.
1019 AbsoluteFrameList floats(aNewParent);
1020 nsIFrame* current = mFloatedList.FirstChild();
1021 while (current) {
1022 nsIFrame* placeholder = current->GetPlaceholderFrame();
1023 nsIFrame* next = current->GetNextSibling();
1024 if (nsLayoutUtils::IsProperAncestorFrame(aNewParent, placeholder)) {
1025 mFloatedList.RemoveFrame(current);
1026 floats.AppendFrame(aNewParent, current);
1027 }
1028 current = next;
1029 }
1030
1031 if (floats.NotEmpty()) {
1032 // Make floats move into aNewParent's float child list in
1033 // ~nsFrameConstructorSaveState() when destructing floatSaveState.
1034 nsFrameConstructorSaveState floatSaveState;
1035 PushFloatContainingBlock(aNewParent, floatSaveState);
1036 mFloatedList = std::move(floats);
1037 }
1038}
1039
1040AbsoluteFrameList* nsFrameConstructorState::GetOutOfFlowFrameList(
1041 nsIFrame* aNewFrame, bool aCanBePositioned, bool aCanBeFloated,
1042 nsFrameState* aPlaceholderType) {
1043 const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
1044 if (aCanBeFloated && disp->IsFloatingStyle()) {
1045 *aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
1046 return &mFloatedList;
1047 }
1048
1049 if (aCanBePositioned) {
1050 if (disp->mTopLayer != StyleTopLayer::None) {
1051 *aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
1052 if (disp->mPosition == StylePositionProperty::Fixed) {
1053 *aPlaceholderType |= PLACEHOLDER_FOR_FIXEDPOS;
1054 return &mRealFixedList;
1055 }
1056 *aPlaceholderType |= PLACEHOLDER_FOR_ABSPOS;
1057 return &mTopLayerAbsoluteList;
1058 }
1059 if (disp->mPosition == StylePositionProperty::Absolute) {
1060 *aPlaceholderType = PLACEHOLDER_FOR_ABSPOS;
1061 return &mAbsoluteList;
1062 }
1063 if (disp->mPosition == StylePositionProperty::Fixed) {
1064 *aPlaceholderType = PLACEHOLDER_FOR_FIXEDPOS;
1065 return mFixedList;
1066 }
1067 }
1068 return nullptr;
1069}
1070
1071void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
1072 nsIFrame* aFrame) {
1073 MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Top)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer
::Top)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer
::Top))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Top"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Top"
")"); do { *((volatile int*)__null) = 1073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1074 nsContainerFrame* frame = do_QueryFrame(aFrame);
1075 if (!frame) {
1076 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"
, 1076)
;
1077 return;
1078 }
1079
1080 ComputedStyle* parentStyle = nsLayoutUtils::GetStyleFrame(aFrame)->Style();
1081 RefPtr<ComputedStyle> style =
1082 mPresShell->StyleSet()->ResolvePseudoElementStyle(
1083 *aContent->AsElement(), PseudoStyleType::backdrop, nullptr,
1084 parentStyle);
1085 MOZ_ASSERT(style->StyleDisplay()->mTopLayer == StyleTopLayer::Top)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(style->StyleDisplay()->mTopLayer == StyleTopLayer
::Top)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(style->StyleDisplay()->mTopLayer == StyleTopLayer
::Top))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("style->StyleDisplay()->mTopLayer == StyleTopLayer::Top"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "style->StyleDisplay()->mTopLayer == StyleTopLayer::Top"
")"); do { *((volatile int*)__null) = 1085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1086 nsContainerFrame* parentFrame =
1087 GetGeometricParent(*style->StyleDisplay(), nullptr);
1088
1089 nsBackdropFrame* backdropFrame =
1090 new (mPresShell) nsBackdropFrame(style, mPresShell->GetPresContext());
1091 backdropFrame->Init(aContent, parentFrame, nullptr);
1092
1093 nsFrameState placeholderType;
1094 AbsoluteFrameList* frameList =
1095 GetOutOfFlowFrameList(backdropFrame, true, true, &placeholderType);
1096 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"
, 1096); AnnotateMozCrashReason("MOZ_ASSERT" "(" "placeholderType & PLACEHOLDER_FOR_TOPLAYER"
")"); do { *((volatile int*)__null) = 1096; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1097
1098 nsIFrame* placeholder = nsCSSFrameConstructor::CreatePlaceholderFrameFor(
1099 mPresShell, aContent, backdropFrame, frame, nullptr, placeholderType);
1100 frame->SetInitialChildList(FrameChildListID::Backdrop,
1101 nsFrameList(placeholder, placeholder));
1102
1103 frameList->AppendFrame(nullptr, backdropFrame);
1104}
1105
1106void nsFrameConstructorState::AddChild(
1107 nsIFrame* aNewFrame, nsFrameList& aFrameList, nsIContent* aContent,
1108 nsContainerFrame* aParentFrame, bool aCanBePositioned, bool aCanBeFloated,
1109 bool aInsertAfter, nsIFrame* aInsertAfterFrame) {
1110 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"
, 1110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFrame->GetNextSibling()"
") (" "Shouldn't happen" ")"); do { *((volatile int*)__null)
= 1110; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1111
1112 nsFrameState placeholderType;
1113 AbsoluteFrameList* outOfFlowFrameList = GetOutOfFlowFrameList(
1114 aNewFrame, aCanBePositioned, aCanBeFloated, &placeholderType);
1115
1116 // The comments in GetGeometricParent regarding root table frames
1117 // all apply here, unfortunately. Thus, we need to check whether
1118 // the returned frame items really has containing block.
1119 nsFrameList* frameList;
1120 if (outOfFlowFrameList && outOfFlowFrameList->mContainingBlock) {
1121 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"
, 1122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
") (" "Parent of the frame is not the containing block?" ")"
); do { *((volatile int*)__null) = 1122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1122 "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"
, 1122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
") (" "Parent of the frame is not the containing block?" ")"
); do { *((volatile int*)__null) = 1122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1123 frameList = outOfFlowFrameList;
1124 } else {
1125 frameList = &aFrameList;
1126 placeholderType = nsFrameState(0);
1127 }
1128
1129 if (placeholderType) {
1130 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"
, 1131); MOZ_PretendNoReturn(); } } while (0)
1131 "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"
, 1131); MOZ_PretendNoReturn(); } } while (0)
;
1132 nsIFrame* placeholderFrame =
1133 nsCSSFrameConstructor::CreatePlaceholderFrameFor(
1134 mPresShell, aContent, aNewFrame, aParentFrame, nullptr,
1135 placeholderType);
1136
1137 placeholderFrame->AddStateBits(mAdditionalStateBits);
1138 // Add the placeholder frame to the flow
1139 aFrameList.AppendFrame(nullptr, placeholderFrame);
1140
1141 if (placeholderType & PLACEHOLDER_FOR_TOPLAYER) {
1142 ConstructBackdropFrameFor(aContent, aNewFrame);
1143 }
1144 }
1145#ifdef DEBUG1
1146 else {
1147 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"
, 1148); MOZ_PretendNoReturn(); } } while (0)
1148 "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"
, 1148); MOZ_PretendNoReturn(); } } while (0)
;
1149 }
1150#endif
1151
1152 if (aInsertAfter) {
1153 frameList->InsertFrame(nullptr, aInsertAfterFrame, aNewFrame);
1154 } else {
1155 frameList->AppendFrame(nullptr, aNewFrame);
1156 }
1157}
1158
1159// Some of this function's callers recurse 1000 levels deep in crashtests. On
1160// platforms where stack limits are low, we can't afford to incorporate this
1161// function's `AutoTArray`s into its callers' stack frames, so disable inlining.
1162MOZ_NEVER_INLINE__attribute__((noinline)) void nsFrameConstructorState::ProcessFrameInsertions(
1163 AbsoluteFrameList& aFrameList, FrameChildListID aChildListID) {
1164 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"
, 1167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1165 &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"
, 1167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1166 &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"
, 1167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1167 &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"
, 1167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1168 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"
, 1169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Float"
")"); do { *((volatile int*)__null) = 1169; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1169 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"
, 1169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Float"
")"); do { *((volatile int*)__null) = 1169; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1170 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"
, 1172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1171 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"
, 1172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1172 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"
, 1172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1173 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"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute"
")"); do { *((volatile int*)__null) = 1174; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1174 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"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute"
")"); do { *((volatile int*)__null) = 1174; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1175 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"
, 1176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1176 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"
, 1176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1177 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"
, 1178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1178; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1178 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"
, 1178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1178; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1179 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"
, 1180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1180; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1180 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"
, 1180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1180; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1181
1182 if (aFrameList.IsEmpty()) {
1183 return;
1184 }
1185
1186 nsContainerFrame* containingBlock = aFrameList.mContainingBlock;
1187
1188 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"
, 1188); MOZ_PretendNoReturn(); } } while (0)
;
1189
1190 if (aChildListID == FrameChildListID::Fixed) {
1191 // Put this frame on the transformed-frame's abs-pos list instead, if
1192 // it has abs-pos children instead of fixed-pos children.
1193 aChildListID = containingBlock->GetAbsoluteListID();
1194 }
1195
1196 // Insert the frames hanging out in aItems. We can use SetInitialChildList()
1197 // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
1198 // is set) and doesn't have any frames in the aChildListID child list yet.
1199 const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
1200 if (childList.IsEmpty() &&
1201 containingBlock->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
1202 // If we're injecting absolutely positioned frames, inject them on the
1203 // absolute containing block
1204 if (aChildListID == containingBlock->GetAbsoluteListID()) {
1205 containingBlock->GetAbsoluteContainingBlock()->SetInitialChildList(
1206 containingBlock, aChildListID, std::move(aFrameList));
1207 } else {
1208 containingBlock->SetInitialChildList(aChildListID, std::move(aFrameList));
1209 }
1210 } else if (aChildListID == FrameChildListID::Fixed ||
1211 aChildListID == FrameChildListID::Absolute) {
1212 // The order is not important for abs-pos/fixed-pos frame list, just
1213 // append the frame items to the list directly.
1214 mFrameConstructor->AppendFrames(containingBlock, aChildListID,
1215 std::move(aFrameList));
1216 } else {
1217 // Note that whether the frame construction context is doing an append or
1218 // not is not helpful here, since it could be appending to some frame in
1219 // the middle of the document, which means we're not necessarily
1220 // appending to the children of the containing block.
1221 //
1222 // We need to make sure the 'append to the end of document' case is fast.
1223 // So first test the last child of the containing block
1224 nsIFrame* lastChild = childList.LastChild();
1225
1226 // CompareTreePosition uses placeholder hierarchy for out of flow frames,
1227 // so this will make out-of-flows respect the ordering of placeholders,
1228 // which is great because it takes care of anonymous content.
1229 nsIFrame* firstNewFrame = aFrameList.FirstChild();
1230
1231 // Cache the ancestor chain so that we can reuse it if needed.
1232 AutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
1233 nsIFrame* notCommonAncestor = nullptr;
1234 if (lastChild) {
1235 notCommonAncestor = nsLayoutUtils::FillAncestors(
1236 firstNewFrame, containingBlock, &firstNewFrameAncestors);
1237 }
1238
1239 if (!lastChild || nsLayoutUtils::CompareTreePosition(
1240 lastChild, firstNewFrame, firstNewFrameAncestors,
1241 notCommonAncestor ? containingBlock : nullptr) < 0) {
1242 // no lastChild, or lastChild comes before the new children, so just
1243 // append
1244 mFrameConstructor->AppendFrames(containingBlock, aChildListID,
1245 std::move(aFrameList));
1246 } else {
1247 // Try the other children. First collect them to an array so that a
1248 // reasonable fast binary search can be used to find the insertion point.
1249 AutoTArray<nsIFrame*, 128> children;
1250 for (nsIFrame* f = childList.FirstChild(); f != lastChild;
1251 f = f->GetNextSibling()) {
1252 children.AppendElement(f);
1253 }
1254
1255 nsIFrame* insertionPoint = nullptr;
1256 int32_t imin = 0;
1257 int32_t max = children.Length();
1258 while (max > imin) {
1259 int32_t imid = imin + ((max - imin) / 2);
1260 nsIFrame* f = children[imid];
1261 int32_t compare = nsLayoutUtils::CompareTreePosition(
1262 f, firstNewFrame, firstNewFrameAncestors,
1263 notCommonAncestor ? containingBlock : nullptr);
1264 if (compare > 0) {
1265 // f is after the new frame.
1266 max = imid;
1267 insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
1268 } else if (compare < 0) {
1269 // f is before the new frame.
1270 imin = imid + 1;
1271 insertionPoint = f;
1272 } else {
1273 // This is for the old behavior. Should be removed once it is
1274 // guaranteed that CompareTreePosition can't return 0!
1275 // See bug 928645.
1276 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"
, 1276)
;
1277 insertionPoint = nullptr;
1278 for (uint32_t i = 0; i < children.Length(); ++i) {
1279 nsIFrame* f = children[i];
1280 if (nsLayoutUtils::CompareTreePosition(
1281 f, firstNewFrame, firstNewFrameAncestors,
1282 notCommonAncestor ? containingBlock : nullptr) > 0) {
1283 break;
1284 }
1285 insertionPoint = f;
1286 }
1287 break;
1288 }
1289 }
1290 mFrameConstructor->InsertFrames(containingBlock, aChildListID,
1291 insertionPoint, std::move(aFrameList));
1292 }
1293 }
1294
1295 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"
, 1295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrameList.IsEmpty()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 1295; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1296}
1297
1298nsFrameConstructorSaveState::~nsFrameConstructorSaveState() {
1299 // Restore the state
1300 if (mList) {
1301 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"
, 1301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mState" ") ("
"Can't have mList set without having a state!" ")"); do { *(
(volatile int*)__null) = 1301; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1302 mState->ProcessFrameInsertions(*mList, mChildListID);
1303
1304 if (mList == &mState->mAbsoluteList) {
1305 mState->mAbsoluteList = std::move(mSavedList);
1306 mState->mFixedList = mSavedFixedList;
1307 } else {
1308 mState->mFloatedList = std::move(mSavedList);
1309 }
1310
1311 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"
, 1312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSavedList.IsEmpty()"
") (" "Frames in mSavedList should've moved back into mState!"
")"); do { *((volatile int*)__null) = 1312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1312 "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"
, 1312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSavedList.IsEmpty()"
") (" "Frames in mSavedList should've moved back into mState!"
")"); do { *((volatile int*)__null) = 1312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1313 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"
, 1314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
") (" "Something corrupted our list!" ")"); do { *((volatile
int*)__null) = 1314; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1314 "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"
, 1314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
") (" "Something corrupted our list!" ")"); do { *((volatile
int*)__null) = 1314; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1315 }
1316}
1317
1318/**
1319 * Moves aFrameList from aOldParent to aNewParent. This updates the parent
1320 * pointer of the frames in the list, and reparents their views as needed.
1321 * nsIFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
1322 * ancestors as needed. Then it sets the list as the initial child list
1323 * on aNewParent, unless aNewParent either already has kids or has been
1324 * reflowed; in that case it appends the new frames. Note that this
1325 * method differs from ReparentFrames in that it doesn't change the kids'
1326 * style.
1327 */
1328// XXXbz Since this is only used for {ib} splits, could we just copy the view
1329// bits from aOldParent to aNewParent and then use the
1330// nsFrameList::ApplySetParent? That would still leave us doing two passes
1331// over the list, of course; if we really wanted to we could factor out the
1332// relevant part of ReparentFrameViewList, I suppose... Or just get rid of
1333// views, which would make most of this function go away.
1334static void MoveChildrenTo(nsIFrame* aOldParent, nsContainerFrame* aNewParent,
1335 nsFrameList& aFrameList) {
1336#ifdef DEBUG1
1337 bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
1338
1339 if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
1340 // Move the frames into the new view
1341 nsContainerFrame::ReparentFrameViewList(aFrameList, aOldParent, aNewParent);
1342 }
1343#endif
1344
1345 aFrameList.ApplySetParent(aNewParent);
1346
1347 if (aNewParent->PrincipalChildList().IsEmpty() &&
1348 aNewParent->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
1349 aNewParent->SetInitialChildList(FrameChildListID::Principal,
1350 std::move(aFrameList));
1351 } else {
1352 aNewParent->AppendFrames(FrameChildListID::Principal,
1353 std::move(aFrameList));
1354 }
1355}
1356
1357static void EnsureAutoPageName(nsFrameConstructorState& aState,
1358 const nsContainerFrame* const aFrame) {
1359 // Check if we need to figure out our used page name.
1360 // When building the entire document, this should only happen for the
1361 // root, which will mean the loop will immediately end. Either way, this will
1362 // only happen once for each time the frame constructor is run.
1363 if (aState.mAutoPageNameValue) {
1364 return;
1365 }
1366
1367 for (const nsContainerFrame* frame = aFrame; frame;
1368 frame = frame->GetParent()) {
1369 if (const nsAtom* maybePageName = frame->GetStylePageName()) {
1370 aState.mAutoPageNameValue = maybePageName;
1371 return;
1372 }
1373 }
1374 // Ensure that a root with `page: auto` gets an empty page name
1375 // https://drafts.csswg.org/css-page-3/#using-named-pages
1376 aState.mAutoPageNameValue = nsGkAtoms::_empty;
1377}
1378
1379nsCSSFrameConstructor::AutoFrameConstructionPageName::
1380 AutoFrameConstructionPageName(nsFrameConstructorState& aState,
1381 nsIFrame* const aFrame)
1382 : mState(aState), mNameToRestore(nullptr) {
1383 if (!aState.mPresContext->IsPaginated()) {
1384 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"
, 1385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aState.mAutoPageNameValue"
") (" "Page name should not have been set" ")"); do { *((volatile
int*)__null) = 1385; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1385 "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"
, 1385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aState.mAutoPageNameValue"
") (" "Page name should not have been set" ")"); do { *((volatile
int*)__null) = 1385; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1386 return;
1387 }
1388#ifdef DEBUG1
1389 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"
, 1390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should only have been visited once" ")"); do { *
((volatile int*)__null) = 1390; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1390 "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"
, 1390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should only have been visited once" ")"); do { *
((volatile int*)__null) = 1390; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1391 aFrame->mWasVisitedByAutoFrameConstructionPageName = true;
1392#endif
1393
1394 EnsureAutoPageName(aState, aFrame->GetParent());
1395 mNameToRestore = aState.mAutoPageNameValue;
1396
1397 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"
, 1398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNameToRestore"
") (" "Page name should have been found by EnsureAutoPageName"
")"); do { *((volatile int*)__null) = 1398; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1398 "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"
, 1398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNameToRestore"
") (" "Page name should have been found by EnsureAutoPageName"
")"); do { *((volatile int*)__null) = 1398; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1399 if (const nsAtom* maybePageName = aFrame->GetStylePageName()) {
1400 aState.mAutoPageNameValue = maybePageName;
1401 }
1402 aFrame->SetAutoPageValue(aState.mAutoPageNameValue);
1403}
1404
1405nsCSSFrameConstructor::AutoFrameConstructionPageName::
1406 ~AutoFrameConstructionPageName() {
1407 // This isn't actually useful when not in paginated layout, but it's very
1408 // likely cheaper to unconditionally write this pointer than to test for
1409 // paginated layout and then branch on the result.
1410 mState.mAutoPageNameValue = mNameToRestore;
1411}
1412
1413//----------------------------------------------------------------------
1414
1415nsCSSFrameConstructor::nsCSSFrameConstructor(Document* aDocument,
1416 PresShell* aPresShell)
1417 : nsFrameManager(aPresShell),
1418 mDocument(aDocument),
1419 mFirstFreeFCItem(nullptr),
1420 mFCItemsInUse(0),
1421 mCurrentDepth(0),
1422 mQuotesDirty(false),
1423 mCountersDirty(false),
1424 mAlwaysCreateFramesForIgnorableWhitespace(false) {
1425#ifdef DEBUG1
1426 static bool gFirstTime = true;
1427 if (gFirstTime) {
1428 gFirstTime = false;
1429 char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
1430 if (flags) {
1431 bool error = false;
1432 for (;;) {
1433 char* comma = strchr(flags, ',');
1434 if (comma) *comma = '\0';
1435
1436 bool found = false;
1437 FrameCtorDebugFlags* flag = gFlags;
1438 FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS(sizeof(gFlags) / sizeof(gFlags[0]));
1439 while (flag < limit) {
1440 if (nsCRT::strcasecmp(flag->name, flags) == 0) {
1441 *(flag->on) = true;
1442 printf("nsCSSFrameConstructor: setting %s debug flag on\n",
1443 flag->name);
1444 found = true;
1445 break;
1446 }
1447 ++flag;
1448 }
1449
1450 if (!found) error = true;
1451
1452 if (!comma) break;
1453
1454 *comma = ',';
1455 flags = comma + 1;
1456 }
1457
1458 if (error) {
1459 printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
1460 FrameCtorDebugFlags* flag = gFlags;
1461 FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS(sizeof(gFlags) / sizeof(gFlags[0]));
1462 while (flag < limit) {
1463 printf(" %s\n", flag->name);
1464 ++flag;
1465 }
1466 printf(
1467 "Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of "
1468 "flag\n");
1469 printf("names (no whitespace)\n");
1470 }
1471 }
1472 }
1473#endif
1474}
1475
1476void nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame) {
1477 if (aFrame->StyleDisplay()->IsContainStyle()) {
1478 mContainStyleScopeManager.DestroyScopesFor(aFrame);
1479 }
1480
1481 if (aFrame->HasAnyStateBits(NS_FRAME_GENERATED_CONTENT) &&
1482 mContainStyleScopeManager.DestroyQuoteNodesFor(aFrame)) {
1483 QuotesDirty();
1484 }
1485
1486 if (aFrame->HasAnyStateBits(NS_FRAME_HAS_CSS_COUNTER_STYLE) &&
1487 mContainStyleScopeManager.DestroyCounterNodesFor(aFrame)) {
1488 // Technically we don't need to update anything if we destroyed only
1489 // USE nodes. However, this is unlikely to happen in the real world
1490 // since USE nodes generally go along with INCREMENT nodes.
1491 CountersDirty();
1492 }
1493
1494 RestyleManager()->NotifyDestroyingFrame(aFrame);
1495}
1496
1497struct nsGenConInitializer {
1498 UniquePtr<nsGenConNode> mNode;
1499 nsGenConList* mList;
1500 void (nsCSSFrameConstructor::*mDirtyAll)();
1501
1502 nsGenConInitializer(UniquePtr<nsGenConNode> aNode, nsGenConList* aList,
1503 void (nsCSSFrameConstructor::*aDirtyAll)())
1504 : mNode(std::move(aNode)), mList(aList), mDirtyAll(aDirtyAll) {}
1505};
1506
1507already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGenConTextNode(
1508 nsFrameConstructorState& aState, const nsAString& aString,
1509 UniquePtr<nsGenConInitializer> aInitializer) {
1510 RefPtr<nsTextNode> content = new (mDocument->NodeInfoManager())
1511 nsTextNode(mDocument->NodeInfoManager());
1512 content->SetText(aString, false);
1513 if (aInitializer) {
1514 aInitializer->mNode->mText = content;
1515 content->SetProperty(nsGkAtoms::genConInitializerProperty,
1516 aInitializer.release(),
1517 nsINode::DeleteProperty<nsGenConInitializer>);
1518 aState.mGeneratedContentWithInitializer.AppendElement(content);
1519 }
1520 return content.forget();
1521}
1522
1523void nsCSSFrameConstructor::CreateGeneratedContent(
1524 nsFrameConstructorState& aState, Element& aOriginatingElement,
1525 ComputedStyle& aPseudoStyle, const StyleContentItem& aItem,
1526 size_t aContentIndex, const FunctionRef<void(nsIContent*)> aAddChild) {
1527 using Type = StyleContentItem::Tag;
1528 // Get the content value
1529 const Type type = aItem.tag;
1530
1531 switch (type) {
1532 case Type::Image: {
1533 RefPtr c = GeneratedImageContent::Create(*mDocument, aContentIndex);
1534 aAddChild(c);
1535 return;
1536 }
1537
1538 case Type::String: {
1539 const auto string = aItem.AsString().AsString();
1540 if (string.IsEmpty()) {
1541 return;
1542 }
1543 RefPtr text =
1544 CreateGenConTextNode(aState, NS_ConvertUTF8toUTF16(string), nullptr);
1545 aAddChild(text);
1546 return;
1547 }
1548
1549 case Type::Attr: {
1550 const auto& attr = aItem.AsAttr();
1551 RefPtr<nsAtom> attrName = attr.attribute.AsAtom();
1552 int32_t attrNameSpace = kNameSpaceID_None;
1553 RefPtr<nsAtom> ns = attr.namespace_url.AsAtom();
1554 if (!ns->IsEmpty()) {
1555 nsresult rv = nsNameSpaceManager::GetInstance()->RegisterNameSpace(
1556 ns.forget(), attrNameSpace);
1557 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"
, 1557); return; } } while (false)
;
1558 }
1559
1560 if (mDocument->IsHTMLDocument() && aOriginatingElement.IsHTMLElement()) {
1561 ToLowerCaseASCII(attrName);
1562 }
1563
1564 RefPtr<nsAtom> fallback = attr.fallback.AsAtom();
1565
1566 nsCOMPtr<nsIContent> content;
1567 NS_NewAttributeContent(mDocument->NodeInfoManager(), attrNameSpace,
1568 attrName, fallback, getter_AddRefs(content));
1569 aAddChild(content);
1570 return;
1571 }
1572
1573 case Type::Counter:
1574 case Type::Counters: {
1575 RefPtr<nsAtom> name;
1576 const StyleCounterStyle* style;
1577 nsString separator;
1578 if (type == Type::Counter) {
1579 const auto& counter = aItem.AsCounter();
1580 name = counter._0.AsAtom();
1581 style = &counter._1;
1582 } else {
1583 const auto& counters = aItem.AsCounters();
1584 name = counters._0.AsAtom();
1585 CopyUTF8toUTF16(counters._1.AsString(), separator);
1586 style = &counters._2;
1587 }
1588
1589 auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
1590 aOriginatingElement, name);
1591 auto node = MakeUnique<nsCounterUseNode>(
1592 *style, std::move(separator), aContentIndex,
1593 /* aAllCounters = */ type == Type::Counters);
1594
1595 auto initializer = MakeUnique<nsGenConInitializer>(
1596 std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
1597 RefPtr c = CreateGenConTextNode(aState, u""_ns, std::move(initializer));
1598 aAddChild(c);
1599 return;
1600 }
1601 case Type::OpenQuote:
1602 case Type::CloseQuote:
1603 case Type::NoOpenQuote:
1604 case Type::NoCloseQuote: {
1605 auto node = MakeUnique<nsQuoteNode>(type, aContentIndex);
1606 auto* quoteList =
1607 mContainStyleScopeManager.QuoteListFor(aOriginatingElement);
1608 auto initializer = MakeUnique<nsGenConInitializer>(
1609 std::move(node), quoteList, &nsCSSFrameConstructor::QuotesDirty);
1610 RefPtr c = CreateGenConTextNode(aState, u""_ns, std::move(initializer));
1611 aAddChild(c);
1612 return;
1613 }
1614
1615 case Type::MozLabelContent: {
1616 nsAutoString accesskey;
1617 if (!aOriginatingElement.GetAttr(nsGkAtoms::accesskey, accesskey) ||
1618 accesskey.IsEmpty() || !LookAndFeel::GetMenuAccessKey()) {
1619 // Easy path: just return a regular value attribute content.
1620 nsCOMPtr<nsIContent> content;
1621 NS_NewAttributeContent(mDocument->NodeInfoManager(), kNameSpaceID_None,
1622 nsGkAtoms::value, nsGkAtoms::_empty,
1623 getter_AddRefs(content));
1624 aAddChild(content);
1625 return;
1626 }
1627
1628 nsAutoString value;
1629 aOriginatingElement.GetAttr(nsGkAtoms::value, value);
1630
1631 auto AppendAccessKeyLabel = [&] {
1632 // Always append accesskey text in uppercase, see bug 1806167.
1633 ToUpperCase(accesskey);
1634 nsAutoString accessKeyLabel = u"("_ns + accesskey + u")"_ns;
1635 if (!StringEndsWith(value, accessKeyLabel)) {
1636 if (InsertSeparatorBeforeAccessKey() && !value.IsEmpty() &&
1637 !NS_IS_SPACE(value.Last())) {
1638 value.Append(' ');
1639 }
1640 value.Append(accessKeyLabel);
1641 }
1642 };
1643 if (AlwaysAppendAccessKey()) {
1644 AppendAccessKeyLabel();
1645 RefPtr c = CreateGenConTextNode(aState, value, nullptr);
1646 aAddChild(c);
1647 return;
1648 }
1649
1650 const auto accessKeyStart = [&]() -> Maybe<size_t> {
1651 nsAString::const_iterator start, end;
1652 value.BeginReading(start);
1653 value.EndReading(end);
1654
1655 const auto originalStart = start;
1656 // not appending access key - do case-sensitive search
1657 // first
1658 bool found = true;
1659 if (!FindInReadable(accesskey, start, end)) {
1660 start = originalStart;
1661 // didn't find it - perform a case-insensitive search
1662 found = FindInReadable(accesskey, start, end,
1663 nsCaseInsensitiveStringComparator);
1664 }
1665 if (!found) {
1666 return Nothing();
1667 }
1668 return Some(Distance(originalStart, start));
1669 }();
1670
1671 if (accessKeyStart.isNothing()) {
1672 AppendAccessKeyLabel();
1673 RefPtr c = CreateGenConTextNode(aState, value, nullptr);
1674 aAddChild(c);
1675 return;
1676 }
1677
1678 if (*accessKeyStart != 0) {
1679 RefPtr beginning = CreateGenConTextNode(
1680 aState, Substring(value, 0, *accessKeyStart), nullptr);
1681 aAddChild(beginning);
1682 }
1683
1684 {
1685 RefPtr accessKeyText = CreateGenConTextNode(
1686 aState, Substring(value, *accessKeyStart, accesskey.Length()),
1687 nullptr);
1688 RefPtr<nsIContent> underline =
1689 mDocument->CreateHTMLElement(nsGkAtoms::u);
1690 underline->AppendChildTo(accessKeyText, /* aNotify = */ false,
1691 IgnoreErrors());
1692 aAddChild(underline);
1693 }
1694
1695 size_t accessKeyEnd = *accessKeyStart + accesskey.Length();
1696 if (accessKeyEnd != value.Length()) {
1697 RefPtr valueEnd = CreateGenConTextNode(
1698 aState, Substring(value, *accessKeyStart + accesskey.Length()),
1699 nullptr);
1700 aAddChild(valueEnd);
1701 }
1702 break;
1703 }
1704 case Type::MozAltContent: {
1705 // Use the "alt" attribute; if that fails and the node is an HTML
1706 // <input>, try the value attribute and then fall back to some default
1707 // localized text we have.
1708 // XXX what if the 'alt' attribute is added later, how will we
1709 // detect that and do the right thing here?
1710 if (aOriginatingElement.HasAttr(nsGkAtoms::alt)) {
1711 nsCOMPtr<nsIContent> content;
1712 NS_NewAttributeContent(mDocument->NodeInfoManager(), kNameSpaceID_None,
1713 nsGkAtoms::alt, nsGkAtoms::_empty,
1714 getter_AddRefs(content));
1715 aAddChild(content);
1716 return;
1717 }
1718
1719 if (aOriginatingElement.IsHTMLElement(nsGkAtoms::input)) {
1720 if (aOriginatingElement.HasAttr(nsGkAtoms::value)) {
1721 nsCOMPtr<nsIContent> content;
1722 NS_NewAttributeContent(mDocument->NodeInfoManager(),
1723 kNameSpaceID_None, nsGkAtoms::value,
1724 nsGkAtoms::_empty, getter_AddRefs(content));
1725 aAddChild(content);
1726 return;
1727 }
1728
1729 nsAutoString temp;
1730 nsContentUtils::GetMaybeLocalizedString(
1731 nsContentUtils::eFORMS_PROPERTIES, "Submit", mDocument, temp);
1732 RefPtr c = CreateGenConTextNode(aState, temp, nullptr);
1733 aAddChild(c);
1734 return;
1735 }
1736 break;
1737 }
1738 }
1739}
1740
1741void nsCSSFrameConstructor::CreateGeneratedContentFromListStyle(
1742 nsFrameConstructorState& aState, Element& aOriginatingElement,
1743 const ComputedStyle& aPseudoStyle,
1744 const FunctionRef<void(nsIContent*)> aAddChild) {
1745 const nsStyleList* styleList = aPseudoStyle.StyleList();
1746 if (!styleList->mListStyleImage.IsNone()) {
1747 RefPtr<nsIContent> child =
1748 GeneratedImageContent::CreateForListStyleImage(*mDocument);
1749 aAddChild(child);
1750 child = CreateGenConTextNode(aState, u" "_ns, nullptr);
1751 aAddChild(child);
1752 return;
1753 }
1754 CreateGeneratedContentFromListStyleType(aState, aOriginatingElement,
1755 aPseudoStyle, aAddChild);
1756}
1757
1758void nsCSSFrameConstructor::CreateGeneratedContentFromListStyleType(
1759 nsFrameConstructorState& aState, Element& aOriginatingElement,
1760 const ComputedStyle& aPseudoStyle,
1761 const FunctionRef<void(nsIContent*)> aAddChild) {
1762 using Tag = StyleCounterStyle::Tag;
1763 const auto& styleType = aPseudoStyle.StyleList()->mListStyleType;
1764 switch (styleType.tag) {
1765 case Tag::None:
1766 return;
1767 case Tag::String: {
1768 nsDependentAtomString string(styleType.AsString().AsAtom());
1769 RefPtr<nsIContent> child = CreateGenConTextNode(aState, string, nullptr);
1770 aAddChild(child);
1771 return;
1772 }
1773 case Tag::Name:
1774 case Tag::Symbols:
1775 break;
1776 }
1777
1778 auto node = MakeUnique<nsCounterUseNode>(nsCounterUseNode::ForLegacyBullet,
1779 styleType);
1780 if (styleType.IsName()) {
1781 nsAtom* name = styleType.AsName().AsAtom();
1782 if (name == nsGkAtoms::disc || name == nsGkAtoms::circle ||
1783 name == nsGkAtoms::square || name == nsGkAtoms::disclosure_closed ||
1784 name == nsGkAtoms::disclosure_open) {
1785 // We don't need a use node inserted for these.
1786 CounterStyle* counterStyle = mPresShell->GetPresContext()
1787 ->CounterStyleManager()
1788 ->ResolveCounterStyle(name);
1789 nsAutoString text;
1790 node->GetText(WritingMode(&aPseudoStyle), counterStyle, text);
1791 // Note that we're done with 'node' in this case. It's not inserted into
1792 // any list so it's deleted when we return.
1793 RefPtr<nsIContent> child = CreateGenConTextNode(aState, text, nullptr);
1794 aAddChild(child);
1795 return;
1796 }
1797 }
1798
1799 auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
1800 aOriginatingElement, nsGkAtoms::list_item);
1801 auto initializer = MakeUnique<nsGenConInitializer>(
1802 std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
1803 RefPtr<nsIContent> child =
1804 CreateGenConTextNode(aState, EmptyString(), std::move(initializer));
1805 aAddChild(child);
1806}
1807
1808// Frames for these may not be leaves in the proper sense, but we still don't
1809// want to expose generated content on them. For the purposes of the page they
1810// should be leaves.
1811static bool HasUAWidget(const Element& aOriginatingElement) {
1812 const ShadowRoot* sr = aOriginatingElement.GetShadowRoot();
1813 return sr && sr->IsUAWidget();
1814}
1815
1816/*
1817 * aParentFrame - the frame that should be the parent of the generated
1818 * content. This is the frame for the corresponding content node,
1819 * which must not be a leaf frame.
1820 *
1821 * Any items created are added to aItems.
1822 *
1823 * We create an XML element (tag _moz_generated_content_before/after/marker)
1824 * representing the pseudoelement. We create a DOM node for each 'content'
1825 * item and make those nodes the children of the XML element. Then we create
1826 * a frame subtree for the XML element as if it were a regular child of
1827 * aParentFrame/aParentContent, giving the XML element the ::before, ::after
1828 * or ::marker style.
1829 */
1830void nsCSSFrameConstructor::CreateGeneratedContentItem(
1831 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
1832 Element& aOriginatingElement, ComputedStyle& aStyle,
1833 PseudoStyleType aPseudoElement, FrameConstructionItemList& aItems,
1834 ItemFlags aExtraFlags) {
1835 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"
, 1838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1838; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1836 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"
, 1838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1838; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1837 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"
, 1838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1838; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1838 "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"
, 1838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1838; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1839
1840 if (HasUAWidget(aOriginatingElement) &&
1841 !aOriginatingElement.IsHTMLElement(nsGkAtoms::details)) {
1842 return;
1843 }
1844
1845 ServoStyleSet* styleSet = mPresShell->StyleSet();
1846
1847 // Probe for the existence of the pseudo-element.
1848 // |ProbePseudoElementStyle| checks the relevant properties for the pseudo.
1849 // It only returns a non-null value if the pseudo should exist.
1850 RefPtr<ComputedStyle> pseudoStyle = styleSet->ProbePseudoElementStyle(
1851 aOriginatingElement, aPseudoElement, nullptr, &aStyle);
1852 if (!pseudoStyle) {
1853 return;
1854 }
1855
1856 nsAtom* elemName = nullptr;
1857 nsAtom* property = nullptr;
1858 switch (aPseudoElement) {
1859 case PseudoStyleType::before:
1860 elemName = nsGkAtoms::mozgeneratedcontentbefore;
1861 property = nsGkAtoms::beforePseudoProperty;
1862 break;
1863 case PseudoStyleType::after:
1864 elemName = nsGkAtoms::mozgeneratedcontentafter;
1865 property = nsGkAtoms::afterPseudoProperty;
1866 break;
1867 case PseudoStyleType::marker:
1868 // We want to get a marker style even if we match no rules, but we still
1869 // want to check the result of GeneratedContentPseudoExists.
1870 elemName = nsGkAtoms::mozgeneratedcontentmarker;
1871 property = nsGkAtoms::markerPseudoProperty;
1872 break;
1873 default:
1874 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"
, 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected aPseudoElement" ")");
do { *((volatile int*)__null) = 1874; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1875 }
1876
1877 RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
1878 elemName, nullptr, kNameSpaceID_None, nsINode::ELEMENT_NODE);
1879 RefPtr<Element> container;
1880 nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
1881 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1882 return;
1883 }
1884
1885 // Cleared when the pseudo is unbound from the tree, so no need to store a
1886 // strong reference, nor a destructor.
1887 aOriginatingElement.SetProperty(property, container.get());
1888
1889 container->SetIsNativeAnonymousRoot();
1890 container->SetPseudoElementType(aPseudoElement);
1891
1892 BindContext context(aOriginatingElement, BindContext::ForNativeAnonymous);
1893 rv = container->BindToTree(context, aOriginatingElement);
1894 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1895 container->UnbindFromTree();
1896 return;
1897 }
1898
1899 if (mDocument->DevToolsAnonymousAndShadowEventsEnabled()) {
1900 container->QueueDevtoolsAnonymousEvent(/* aIsRemove = */ false);
1901 }
1902
1903 // Servo has already eagerly computed the style for the container, so we can
1904 // just stick the style on the element and avoid an additional traversal.
1905 //
1906 // We don't do this for pseudos that may trigger animations or transitions,
1907 // since those need to be kicked off by the traversal machinery.
1908 //
1909 // Note that when a pseudo-element animates, we flag the originating element,
1910 // so we check that flag, but we could also a more expensive (but exhaustive)
1911 // check using EffectSet::GetEffectSet, for example.
1912 if (!Servo_ComputedValues_SpecifiesAnimationsOrTransitions(pseudoStyle) &&
1913 !aOriginatingElement.MayHaveAnimations()) {
1914 Servo_SetExplicitStyle(container, pseudoStyle);
1915 } else {
1916 // If animations are involved, we avoid the SetExplicitStyle optimization
1917 // above. We need to grab style with animations from the pseudo element and
1918 // replace old one.
1919 mPresShell->StyleSet()->StyleNewSubtree(container);
1920 pseudoStyle = ServoStyleSet::ResolveServoStyle(*container);
1921 }
1922
1923 auto AppendChild = [&container, this](nsIContent* aChild) {
1924 // We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
1925 // here; it would get set under AppendChildTo. But AppendChildTo might
1926 // think that we're going from not being anonymous to being anonymous and
1927 // do some extra work; setting the flag here avoids that.
1928 aChild->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
1929 container->AppendChildTo(aChild, false, IgnoreErrors());
1930 if (auto* childElement = Element::FromNode(aChild)) {
1931 // If we created any children elements, Servo needs to traverse them, but
1932 // the root is already set up.
1933 mPresShell->StyleSet()->StyleNewSubtree(childElement);
1934 }
1935 };
1936 auto items = pseudoStyle->StyleContent()->NonAltContentItems();
1937 size_t index = 0;
1938 for (const auto& item : items) {
1939 CreateGeneratedContent(aState, aOriginatingElement, *pseudoStyle, item,
1940 index++, AppendChild);
1941 }
1942 // If a ::marker has no 'content' then generate it from its 'list-style-*'.
1943 if (index == 0 && aPseudoElement == PseudoStyleType::marker) {
1944 CreateGeneratedContentFromListStyle(aState, aOriginatingElement,
1945 *pseudoStyle, AppendChild);
1946 }
1947 auto flags = ItemFlags{ItemFlag::IsGeneratedContent} + aExtraFlags;
1948 AddFrameConstructionItemsInternal(aState, container, aParentFrame, true,
1949 pseudoStyle, flags, aItems);
1950}
1951
1952/****************************************************
1953 ** BEGIN TABLE SECTION
1954 ****************************************************/
1955
1956// The term pseudo frame is being used instead of anonymous frame, since
1957// anonymous frame has been used elsewhere to refer to frames that have
1958// generated content
1959
1960// Return whether the given frame is a table pseudo-frame. Note that
1961// cell-content and table-outer frames have pseudo-types, but are always
1962// created, even for non-anonymous cells and tables respectively. So for those
1963// we have to examine the cell or table frame to see whether it's a pseudo
1964// frame. In particular, a lone table caption will have a table wrapper as its
1965// parent, but will also trigger construction of an empty inner table, which
1966// will be the one we can examine to see whether the wrapper was a pseudo-frame.
1967static bool IsTablePseudo(nsIFrame* aFrame) {
1968 auto pseudoType = aFrame->Style()->GetPseudoType();
1969 if (pseudoType == PseudoStyleType::NotPseudo) {
1970 return false;
1971 }
1972 return pseudoType == PseudoStyleType::table ||
1973 pseudoType == PseudoStyleType::inlineTable ||
1974 pseudoType == PseudoStyleType::tableColGroup ||
1975 pseudoType == PseudoStyleType::tableRowGroup ||
1976 pseudoType == PseudoStyleType::tableRow ||
1977 pseudoType == PseudoStyleType::tableCell ||
1978 (pseudoType == PseudoStyleType::cellContent &&
1979 aFrame->GetParent()->Style()->GetPseudoType() ==
1980 PseudoStyleType::tableCell) ||
1981 (pseudoType == PseudoStyleType::tableWrapper &&
1982 aFrame->PrincipalChildList()
1983 .FirstChild()
1984 ->Style()
1985 ->IsPseudoOrAnonBox());
1986}
1987
1988static bool IsRubyPseudo(nsIFrame* aFrame) {
1989 return RubyUtils::IsRubyPseudo(aFrame->Style()->GetPseudoType());
1990}
1991
1992// Note that this is (subtly) different to ParentIsWrapperAnonBox, since
1993// ParentIsWrapperAnonBox is really just about restyles, but there are wrapper
1994// anon boxes that don't need to return true for that...
1995// FIXME(emilio): This should be less complicated, ParentIsWrapperAnonBox should
1996// probably be renamed to something else, and this should just use
1997// IsWrapperAnonBox or similar...
1998static bool IsWrapperPseudo(nsIFrame* aFrame) {
1999 auto pseudoType = aFrame->Style()->GetPseudoType();
2000 if (!PseudoStyle::IsAnonBox(pseudoType)) {
2001 return false;
2002 }
2003 return PseudoStyle::IsWrapperAnonBox(pseudoType) || IsTablePseudo(aFrame);
2004}
2005
2006/* static */
2007nsCSSFrameConstructor::ParentType nsCSSFrameConstructor::GetParentType(
2008 LayoutFrameType aFrameType) {
2009 if (aFrameType == LayoutFrameType::Table) {
2010 return eTypeTable;
2011 }
2012 if (aFrameType == LayoutFrameType::TableRowGroup) {
2013 return eTypeRowGroup;
2014 }
2015 if (aFrameType == LayoutFrameType::TableRow) {
2016 return eTypeRow;
2017 }
2018 if (aFrameType == LayoutFrameType::TableColGroup) {
2019 return eTypeColGroup;
2020 }
2021 if (aFrameType == LayoutFrameType::RubyBaseContainer) {
2022 return eTypeRubyBaseContainer;
2023 }
2024 if (aFrameType == LayoutFrameType::RubyTextContainer) {
2025 return eTypeRubyTextContainer;
2026 }
2027 if (aFrameType == LayoutFrameType::Ruby) {
2028 return eTypeRuby;
2029 }
2030
2031 return eTypeBlock;
2032}
2033
2034// Pull all the captions present in aItems out into aCaptions.
2035static void PullOutCaptionFrames(nsFrameList& aList, nsFrameList& aCaptions) {
2036 nsIFrame* child = aList.FirstChild();
2037 while (child) {
2038 nsIFrame* nextSibling = child->GetNextSibling();
2039 if (child->StyleDisplay()->mDisplay == StyleDisplay::TableCaption) {
2040 aList.RemoveFrame(child);
2041 aCaptions.AppendFrame(nullptr, child);
2042 }
2043 child = nextSibling;
2044 }
2045}
2046
2047// Construct the outer, inner table frames and the children frames for the
2048// table.
2049// XXX Page break frames for pseudo table frames are not constructed to avoid
2050// the risk associated with revising the pseudo frame mechanism. The long term
2051// solution of having frames handle page-break-before/after will solve the
2052// problem.
2053nsIFrame* nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
2054 FrameConstructionItem& aItem,
2055 nsContainerFrame* aParentFrame,
2056 const nsStyleDisplay* aDisplay,
2057 nsFrameList& aFrameList) {
2058 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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2060; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
2059 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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2060; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
2060 "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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2060; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2061
2062 nsIContent* const content = aItem.mContent;
2063 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2064 const bool isMathMLContent = content->IsMathMLElement();
2065
2066 // create the pseudo SC for the table wrapper as a child of the inner SC
2067 RefPtr<ComputedStyle> outerComputedStyle =
2068 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2069 PseudoStyleType::tableWrapper, computedStyle);
2070
2071 // Create the table wrapper frame which holds the caption and inner table
2072 // frame
2073 nsContainerFrame* newFrame;
2074 if (isMathMLContent)
2075 newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerComputedStyle);
2076 else
2077 newFrame = NS_NewTableWrapperFrame(mPresShell, outerComputedStyle);
2078
2079 nsContainerFrame* geometricParent = aState.GetGeometricParent(
2080 *outerComputedStyle->StyleDisplay(), aParentFrame);
2081
2082 // Init the table wrapper frame
2083 InitAndRestoreFrame(aState, content, geometricParent, newFrame);
2084
2085 // Create the inner table frame
2086 nsContainerFrame* innerFrame;
2087 if (isMathMLContent)
2088 innerFrame = NS_NewMathMLmtableFrame(mPresShell, computedStyle);
2089 else
2090 innerFrame = NS_NewTableFrame(mPresShell, computedStyle);
2091
2092 InitAndRestoreFrame(aState, content, newFrame, innerFrame);
2093 innerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2094
2095 // Put the newly created frames into the right child list
2096 SetInitialSingleChild(newFrame, innerFrame);
2097
2098 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
2099
2100 if (!mRootElementFrame) {
2101 mRootElementFrame = newFrame;
2102 }
2103
2104 nsFrameList childList;
2105
2106 // Process children
2107 nsFrameConstructorSaveState absoluteSaveState;
2108
2109 // Mark the table frame as an absolute container if needed
2110 newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2111 if (newFrame->IsAbsPosContainingBlock()) {
2112 aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
2113 }
2114
2115 nsFrameConstructorSaveState floatSaveState;
2116 aState.MaybePushFloatContainingBlock(innerFrame, floatSaveState);
2117
2118 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2119 ConstructFramesFromItemList(
2120 aState, aItem.mChildItems, innerFrame,
2121 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2122 } else {
2123 ProcessChildren(aState, content, computedStyle, innerFrame, true, childList,
2124 false);
2125 }
2126
2127 nsFrameList captionList;
2128 PullOutCaptionFrames(childList, captionList);
2129
2130 // Set the inner table frame's initial primary list
2131 innerFrame->SetInitialChildList(FrameChildListID::Principal,
2132 std::move(childList));
2133
2134 // Set the table wrapper frame's secondary childlist lists
2135 if (captionList.NotEmpty()) {
2136 captionList.ApplySetParent(newFrame);
2137 newFrame->SetInitialChildList(FrameChildListID::Caption,
2138 std::move(captionList));
2139 }
2140
2141 return newFrame;
2142}
2143
2144static void MakeTablePartAbsoluteContainingBlock(
2145 nsFrameConstructorState& aState, nsFrameConstructorSaveState& aAbsSaveState,
2146 nsContainerFrame* aFrame) {
2147 // If we're positioned, then we need to become an absolute containing block
2148 // for any absolutely positioned children.
2149 aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2150 if (aFrame->IsAbsPosContainingBlock()) {
2151 aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
2152 }
2153}
2154
2155nsIFrame* nsCSSFrameConstructor::ConstructTableRowOrRowGroup(
2156 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2157 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
2158 nsFrameList& aFrameList) {
2159 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"
, 2163); 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
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2160 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"
, 2163); 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
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2161 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"
, 2163); 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
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2162 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"
, 2163); 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
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2163 "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"
, 2163); 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
) = 2163; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2164 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"
, 2165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem.mComputedStyle->StyleDisplay() == aDisplay"
") (" "Display style doesn't match style" ")"); do { *((volatile
int*)__null) = 2165; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2165 "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"
, 2165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem.mComputedStyle->StyleDisplay() == aDisplay"
") (" "Display style doesn't match style" ")"); do { *((volatile
int*)__null) = 2165; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2166 nsIContent* const content = aItem.mContent;
2167 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2168
2169 nsContainerFrame* newFrame;
2170 if (aDisplay->mDisplay == StyleDisplay::TableRow) {
2171 if (content->IsMathMLElement())
2172 newFrame = NS_NewMathMLmtrFrame(mPresShell, computedStyle);
2173 else
2174 newFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
2175 } else {
2176 newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
2177 }
2178
2179 InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
2180
2181 nsFrameConstructorSaveState absoluteSaveState;
2182 MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, newFrame);
2183
2184 nsFrameConstructorSaveState floatSaveState;
2185 aState.MaybePushFloatContainingBlock(newFrame, floatSaveState);
2186
2187 nsFrameList childList;
2188 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2189 ConstructFramesFromItemList(
2190 aState, aItem.mChildItems, newFrame,
2191 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2192 } else {
2193 ProcessChildren(aState, content, computedStyle, newFrame, true, childList,
2194 false);
2195 }
2196
2197 newFrame->SetInitialChildList(FrameChildListID::Principal,
2198 std::move(childList));
2199 aFrameList.AppendFrame(nullptr, newFrame);
2200 return newFrame;
2201}
2202
2203nsIFrame* nsCSSFrameConstructor::ConstructTableCol(
2204 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2205 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
2206 nsFrameList& aFrameList) {
2207 nsIContent* const content = aItem.mContent;
2208 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2209
2210 nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, computedStyle);
2211 InitAndRestoreFrame(aState, content, aParentFrame, colFrame);
2212
2213 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"
, 2213); MOZ_PretendNoReturn(); } } while (0)
;
2214
2215 aFrameList.AppendFrame(nullptr, colFrame);
2216
2217 // construct additional col frames if the col frame has a span > 1
2218 int32_t span = colFrame->GetSpan();
2219 for (int32_t spanX = 1; spanX < span; spanX++) {
2220 nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, computedStyle);
2221 InitAndRestoreFrame(aState, content, aParentFrame, newCol, false);
2222 aFrameList.LastChild()->SetNextContinuation(newCol);
2223 newCol->SetPrevContinuation(aFrameList.LastChild());
2224 aFrameList.AppendFrame(nullptr, newCol);
2225 newCol->SetColType(eColAnonymousCol);
2226 }
2227
2228 return colFrame;
2229}
2230
2231nsIFrame* nsCSSFrameConstructor::ConstructTableCell(
2232 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2233 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
2234 nsFrameList& aFrameList) {
2235 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"
, 2235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableCell"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2235; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2236
2237 nsIContent* const content = aItem.mContent;
2238 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2239 const bool isMathMLContent = content->IsMathMLElement();
2240
2241 nsTableFrame* tableFrame =
2242 static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
2243 nsContainerFrame* cellFrame;
2244 // <mtable> is border separate in mathml.css and the MathML code doesn't
2245 // implement border collapse. For those users who style <mtable> with border
2246 // collapse, give them the default non-MathML table frames that understand
2247 // border collapse. This won't break us because MathML table frames are all
2248 // subclasses of the default table code, and so we can freely mix <mtable>
2249 // with <mtr> or <tr>, <mtd> or <td>. What will happen is just that non-MathML
2250 // frames won't understand MathML attributes and will therefore miss the
2251 // special handling that the MathML code does.
2252 if (isMathMLContent && !tableFrame->IsBorderCollapse()) {
2253 cellFrame = NS_NewMathMLmtdFrame(mPresShell, computedStyle, tableFrame);
2254 } else {
2255 // Warning: If you change this and add a wrapper frame around table cell
2256 // frames, make sure Bug 368554 doesn't regress!
2257 // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
2258 cellFrame = NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
2259 }
2260
2261 // Initialize the table cell frame
2262 InitAndRestoreFrame(aState, content, aParentFrame, cellFrame);
2263 cellFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2264
2265 // Resolve pseudo style and initialize the body cell frame
2266 RefPtr<ComputedStyle> innerPseudoStyle =
2267 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2268 PseudoStyleType::cellContent, computedStyle);
2269
2270 nsContainerFrame* cellInnerFrame;
2271 nsContainerFrame* scrollFrame = nullptr;
2272 bool isScrollable = false;
2273 // Create a block frame that will format the cell's content
2274 if (isMathMLContent) {
2275 cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
2276 } else {
2277 isScrollable = innerPseudoStyle->StyleDisplay()->IsScrollableOverflow() &&
2278 !aState.mPresContext->IsPaginated() &&
2279 StaticPrefs::layout_tables_scrollable_cells();
2280 if (isScrollable) {
2281 innerPseudoStyle = BeginBuildingScrollContainerFrame(
2282 aState, content, innerPseudoStyle, cellFrame,
2283 PseudoStyleType::scrolledContent, false, scrollFrame);
2284 }
2285 cellInnerFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle);
2286 }
2287 auto* parent = scrollFrame ? scrollFrame : cellFrame;
2288 InitAndRestoreFrame(aState, content, parent, cellInnerFrame);
2289
2290 nsFrameConstructorSaveState absoluteSaveState;
2291 MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, cellFrame);
2292
2293 nsFrameConstructorSaveState floatSaveState;
2294 aState.MaybePushFloatContainingBlock(cellInnerFrame, floatSaveState);
2295
2296 nsFrameList childList;
2297 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2298 AutoFrameConstructionPageName pageNameTracker(aState, cellInnerFrame);
2299 ConstructFramesFromItemList(
2300 aState, aItem.mChildItems, cellInnerFrame,
2301 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2302 } else {
2303 // Process the child content
2304 ProcessChildren(aState, content, computedStyle, cellInnerFrame, true,
2305 childList, !isMathMLContent);
2306 }
2307
2308 cellInnerFrame->SetInitialChildList(FrameChildListID::Principal,
2309 std::move(childList));
2310
2311 if (isScrollable) {
2312 FinishBuildingScrollContainerFrame(scrollFrame, cellInnerFrame);
2313 }
2314 SetInitialSingleChild(cellFrame, scrollFrame ? scrollFrame : cellInnerFrame);
2315 aFrameList.AppendFrame(nullptr, cellFrame);
2316 return cellFrame;
2317}
2318
2319static inline bool NeedFrameFor(const nsFrameConstructorState& aState,
2320 nsContainerFrame* aParentFrame,
2321 nsIContent* aChildContent) {
2322 // XXX the GetContent() != aChildContent check is needed due to bug 135040.
2323 // Remove it once that's fixed.
2324 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"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2327; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2325 !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"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2327; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2326 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"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2327; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2327 "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"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2327; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2328
2329 // don't create a whitespace frame if aParentFrame doesn't want it.
2330 // always create frames for children in generated content. counter(),
2331 // quotes, and attr() content can easily change dynamically and we don't
2332 // want to be reconstructing frames. It's not even clear that these
2333 // should be considered ignorable just because they evaluate to
2334 // whitespace.
2335
2336 // We could handle all this in CreateNeededPseudoContainers or some other
2337 // place after we build our frame construction items, but that would involve
2338 // creating frame construction items for whitespace kids that ignores
2339 // white-space, where we know we'll be dropping them all anyway, and involve
2340 // an extra walk down the frame construction item list.
2341 auto excludesIgnorableWhitespace = [](nsIFrame* aParentFrame) {
2342 return aParentFrame->IsMathMLFrame();
2343 };
2344 if (!aParentFrame || !excludesIgnorableWhitespace(aParentFrame) ||
2345 aParentFrame->IsGeneratedContentFrame() || !aChildContent->IsText()) {
2346 return true;
2347 }
2348
2349 aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
2350 NS_REFRAME_IF_WHITESPACE);
2351 return !aChildContent->TextIsOnlyWhitespace();
2352}
2353
2354/***********************************************
2355 * END TABLE SECTION
2356 ***********************************************/
2357
2358nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
2359 Element* aDocElement) {
2360 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"
, 2361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetRootFrame()"
") (" "No viewport? Someone forgot to call ConstructRootFrame!"
")"); do { *((volatile int*)__null) = 2361; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2361 "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"
, 2361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetRootFrame()"
") (" "No viewport? Someone forgot to call ConstructRootFrame!"
")"); do { *((volatile int*)__null) = 2361; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2362 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"
, 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDocElementContainingBlock"
") (" "Shouldn't have a doc element containing block here" ")"
); do { *((volatile int*)__null) = 2363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2363 "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"
, 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDocElementContainingBlock"
") (" "Shouldn't have a doc element containing block here" ")"
); do { *((volatile int*)__null) = 2363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2364
2365 // Resolve a new style for the viewport since it may be affected by a new root
2366 // element style (e.g. a propagated 'direction').
2367 //
2368 // @see ComputedStyle::ApplyStyleFixups
2369 {
2370 RefPtr<ComputedStyle> sc =
2371 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2372 PseudoStyleType::viewport, nullptr);
2373 GetRootFrame()->SetComputedStyleWithoutNotification(sc);
2374 }
2375
2376 // Ensure the document element is styled at this point.
2377 if (!aDocElement->HasServoData()) {
2378 mPresShell->StyleSet()->StyleNewSubtree(aDocElement);
2379 }
2380 aDocElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
2381
2382 // Make sure to call UpdateViewportScrollStylesOverride before
2383 // SetUpDocElementContainingBlock, since it sets up our scrollbar state
2384 // properly.
2385 DebugOnly<nsIContent*> propagatedScrollFrom;
2386 if (nsPresContext* presContext = mPresShell->GetPresContext()) {
2387 propagatedScrollFrom = presContext->UpdateViewportScrollStylesOverride();
2388 }
2389
2390 SetUpDocElementContainingBlock(aDocElement);
2391
2392 // This has the side-effect of getting `mFrameTreeState` from our docshell.
2393 //
2394 // FIXME(emilio): There may be a more sensible time to do this.
2395 if (!mFrameTreeState) {
2396 mPresShell->CaptureHistoryState(getter_AddRefs(mFrameTreeState));
2397 }
2398
2399 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"
, 2399); MOZ_PretendNoReturn(); } } while (0)
;
2400 nsFrameConstructorState state(
2401 mPresShell,
2402 GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS),
2403 nullptr, nullptr, do_AddRef(mFrameTreeState));
2404
2405 RefPtr<ComputedStyle> computedStyle =
2406 ServoStyleSet::ResolveServoStyle(*aDocElement);
2407
2408 const nsStyleDisplay* display = computedStyle->StyleDisplay();
2409
2410 // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
2411
2412 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"
, 2415); MOZ_PretendNoReturn(); } } while (0)
2413 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"
, 2415); MOZ_PretendNoReturn(); } } while (0)
2414 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"
, 2415); MOZ_PretendNoReturn(); } } while (0)
2415 "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"
, 2415); MOZ_PretendNoReturn(); } } while (0)
;
2416
2417 if (MOZ_UNLIKELY(display->mDisplay == StyleDisplay::None)(__builtin_expect(!!(display->mDisplay == StyleDisplay::None
), 0))
) {
2418 return nullptr;
2419 }
2420
2421 // This implements "The Principal Writing Mode".
2422 // https://drafts.csswg.org/css-writing-modes-3/#principal-flow
2423 //
2424 // If there's a <body> element in an HTML document, its writing-mode,
2425 // direction, and text-orientation override the root element's used value.
2426 //
2427 // We need to copy <body>'s WritingMode to mDocElementContainingBlock before
2428 // construct mRootElementFrame so that anonymous internal frames such as
2429 // <html> with table style can copy their parent frame's mWritingMode in
2430 // nsIFrame::Init().
2431 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"
, 2433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2433; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2432 "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"
, 2433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2433; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2433 "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"
, 2433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2433; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2434
2435 const WritingMode propagatedWM = [&] {
2436 const WritingMode rootWM(computedStyle);
2437 if (computedStyle->StyleDisplay()->IsContainAny()) {
2438 return rootWM;
2439 }
2440 Element* body = mDocument->GetBodyElement();
2441 if (!body) {
2442 return rootWM;
2443 }
2444 RefPtr<ComputedStyle> bodyStyle = ResolveComputedStyle(body);
2445 if (bodyStyle->StyleDisplay()->IsContainAny()) {
2446 return rootWM;
2447 }
2448 const WritingMode bodyWM(bodyStyle);
2449 if (bodyWM != rootWM) {
2450 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "Layout"_ns,
2451 mDocument,
2452 nsContentUtils::eLAYOUT_PROPERTIES,
2453 "PrincipalWritingModePropagationWarning");
2454 }
2455 return bodyWM;
2456 }();
2457
2458 mDocElementContainingBlock->PropagateWritingModeToSelfAndAncestors(
2459 propagatedWM);
2460
2461 // Push the absolute containing block now so we can absolutely position the
2462 // root element
2463 nsFrameConstructorSaveState canvasCbSaveState;
2464 mCanvasFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2465
2466 state.PushAbsoluteContainingBlock(mCanvasFrame, mCanvasFrame,
2467 canvasCbSaveState);
2468
2469 nsFrameConstructorSaveState docElementCbSaveState;
2470 if (mCanvasFrame != mDocElementContainingBlock) {
2471 mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2472 state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
2473 mDocElementContainingBlock,
2474 docElementCbSaveState);
2475 }
2476
2477 // The rules from CSS 2.1, section 9.2.4, have already been applied
2478 // by the style system, so we can assume that display->mDisplay is
2479 // either NONE, BLOCK, or TABLE.
2480
2481 // contentFrame is the primary frame for the root element. frameList contains
2482 // the children of the initial containing block.
2483 //
2484 // The first of those frames is usually `contentFrame`, but it can be
2485 // different, in particular if the root frame is positioned, in which case
2486 // contentFrame is the out-of-flow frame and frameList.FirstChild() is the
2487 // placeholder.
2488 //
2489 // The rest of the frames in frameList are the anonymous content of the canvas
2490 // frame.
2491 nsContainerFrame* contentFrame;
2492 nsFrameList frameList;
2493 bool processChildren = false;
2494
2495 nsFrameConstructorSaveState absoluteSaveState;
2496
2497 if (aDocElement->IsSVGElement()) {
2498 if (!aDocElement->IsSVGElement(nsGkAtoms::svg)) {
2499 return nullptr;
2500 }
2501 // We're going to call the right function ourselves, so no need to give a
2502 // function to this FrameConstructionData.
2503
2504 // XXXbz on the other hand, if we converted this whole function to
2505 // FrameConstructionData/Item, then we'd need the right function
2506 // here... but would probably be able to get away with less code in this
2507 // function in general.
2508 static constexpr FrameConstructionData rootSVGData;
2509 AutoFrameConstructionItem item(this, &rootSVGData, aDocElement,
2510 do_AddRef(computedStyle), true);
2511
2512 contentFrame = static_cast<nsContainerFrame*>(ConstructOuterSVG(
2513 state, item, mDocElementContainingBlock, display, frameList));
2514 } else if (display->mDisplay == StyleDisplay::Flex ||
2515 display->mDisplay == StyleDisplay::WebkitBox ||
2516 display->mDisplay == StyleDisplay::Grid) {
2517 auto func = [&] {
2518 if (display->mDisplay == StyleDisplay::Grid) {
2519 return NS_NewGridContainerFrame;
2520 }
2521 return NS_NewFlexContainerFrame;
2522 }();
2523 contentFrame = func(mPresShell, computedStyle);
2524 InitAndRestoreFrame(
2525 state, aDocElement,
2526 state.GetGeometricParent(*display, mDocElementContainingBlock),
2527 contentFrame);
2528 state.AddChild(contentFrame, frameList, aDocElement,
2529 mDocElementContainingBlock);
2530 processChildren = true;
2531
2532 contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2533 if (contentFrame->IsAbsPosContainingBlock()) {
2534 state.PushAbsoluteContainingBlock(contentFrame, contentFrame,
2535 absoluteSaveState);
2536 }
2537 } else if (display->mDisplay == StyleDisplay::Table) {
2538 // We're going to call the right function ourselves, so no need to give a
2539 // function to this FrameConstructionData.
2540
2541 // XXXbz on the other hand, if we converted this whole function to
2542 // FrameConstructionData/Item, then we'd need the right function
2543 // here... but would probably be able to get away with less code in this
2544 // function in general.
2545 static constexpr FrameConstructionData rootTableData;
2546 AutoFrameConstructionItem item(this, &rootTableData, aDocElement,
2547 do_AddRef(computedStyle), true);
2548
2549 // if the document is a table then just populate it.
2550 contentFrame = static_cast<nsContainerFrame*>(ConstructTable(
2551 state, item, mDocElementContainingBlock, display, frameList));
2552 } else if (display->DisplayInside() == StyleDisplayInside::Ruby) {
2553 static constexpr FrameConstructionData data(
2554 &nsCSSFrameConstructor::ConstructBlockRubyFrame);
2555 AutoFrameConstructionItem item(this, &data, aDocElement,
2556 do_AddRef(computedStyle), true);
2557 contentFrame = static_cast<nsContainerFrame*>(ConstructBlockRubyFrame(
2558 state, item,
2559 state.GetGeometricParent(*display, mDocElementContainingBlock), display,
2560 frameList));
2561 } else {
2562 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"
, 2564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2564; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2563 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"
, 2564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2564; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2564 "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"
, 2564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2564; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2565 contentFrame = NS_NewBlockFrame(mPresShell, computedStyle);
2566 ConstructBlock(
2567 state, aDocElement,
2568 state.GetGeometricParent(*display, mDocElementContainingBlock),
2569 mDocElementContainingBlock, computedStyle, &contentFrame, frameList,
2570 contentFrame->IsAbsPosContainingBlock() ? contentFrame : nullptr);
2571 }
2572
2573 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"
, 2573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "frameList.FirstChild()"
")"); do { *((volatile int*)__null) = 2573; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2574 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"
, 2574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "frameList.FirstChild()->GetContent() == aDocElement"
")"); do { *((volatile int*)__null) = 2574; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2575 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"
, 2575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentFrame"
")"); do { *((volatile int*)__null) = 2575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2576
2577 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"
, 2579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2579; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2578 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"
, 2579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2579; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2579 "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"
, 2579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2579; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2580 if (processChildren) {
2581 mRootElementFrame = contentFrame;
2582 }
2583
2584 // Figure out which frame has the main style for the document element,
2585 // assigning it to mRootElementStyleFrame.
2586 // Backgrounds should be propagated from that frame to the viewport.
2587 contentFrame->GetParentComputedStyle(&mRootElementStyleFrame);
2588 bool isChild = mRootElementStyleFrame &&
2589 mRootElementStyleFrame->GetParent() == contentFrame;
2590 if (!isChild) {
2591 mRootElementStyleFrame = mRootElementFrame;
2592 }
2593
2594 if (processChildren) {
2595 // Still need to process the child content
2596 nsFrameList childList;
2597
2598 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"
, 2600); MOZ_PretendNoReturn(); } } while (0)
2599 !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"
, 2600); MOZ_PretendNoReturn(); } } while (0)
2600 "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"
, 2600); MOZ_PretendNoReturn(); } } while (0)
;
2601
2602 nsFrameConstructorSaveState floatSaveState;
2603 state.MaybePushFloatContainingBlock(contentFrame, floatSaveState);
2604
2605 ProcessChildren(state, aDocElement, computedStyle, contentFrame, true,
2606 childList, false);
2607
2608 // Set the initial child lists
2609 contentFrame->SetInitialChildList(FrameChildListID::Principal,
2610 std::move(childList));
2611 }
2612
2613 nsIFrame* newFrame = frameList.FirstChild();
2614 // set the primary frame
2615 aDocElement->SetPrimaryFrame(contentFrame);
2616 mDocElementContainingBlock->AppendFrames(FrameChildListID::Principal,
2617 std::move(frameList));
2618
2619 // NOTE(emilio): This is in the reverse order compared to normal anonymous
2620 // children. We usually generate anonymous kids first, then non-anonymous,
2621 // but we generate the doc element frame the other way around. This is fine
2622 // either way, but generating anonymous children in a different order requires
2623 // changing nsCanvasFrame (and a whole lot of other potentially unknown code)
2624 // to look at the last child to find the root frame rather than the first
2625 // child.
2626 ConstructAnonymousContentForCanvas(
2627 state, mCanvasFrame, mRootElementFrame->GetContent(), frameList);
2628 mCanvasFrame->AppendFrames(FrameChildListID::Principal, std::move(frameList));
2629
2630 return newFrame;
2631}
2632
2633RestyleManager* nsCSSFrameConstructor::RestyleManager() const {
2634 return mPresShell->GetPresContext()->RestyleManager();
2635}
2636
2637ViewportFrame* nsCSSFrameConstructor::ConstructRootFrame() {
2638 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ConstructRootFrame",mozilla::AutoProfilerLabelHot raiiObject2639( "nsCSSFrameConstructor::ConstructRootFrame"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
2639 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject2639( "nsCSSFrameConstructor::ConstructRootFrame"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
2640 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
2641
2642 ServoStyleSet* styleSet = mPresShell->StyleSet();
2643
2644 // --------- BUILD VIEWPORT -----------
2645 RefPtr<ComputedStyle> viewportPseudoStyle =
2646 styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::viewport,
2647 nullptr);
2648 ViewportFrame* viewportFrame =
2649 NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
2650
2651 // XXXbz do we _have_ to pass a null content pointer to that frame?
2652 // Would it really kill us to pass in the root element or something?
2653 // What would that break?
2654 viewportFrame->Init(nullptr, nullptr, nullptr);
2655
2656 viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2657
2658 // Bind the viewport frame to the root view
2659 if (nsView* rootView = mPresShell->GetViewManager()->GetRootView()) {
2660 viewportFrame->SetView(rootView);
2661 viewportFrame->SyncFrameViewProperties(rootView);
2662 rootView->SetNeedsWindowPropertiesSync();
2663 }
2664
2665 // Make it an absolute container for fixed-pos elements
2666 viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2667 viewportFrame->MarkAsAbsoluteContainingBlock();
2668
2669 return viewportFrame;
2670}
2671
2672void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
2673 nsIContent* aDocElement) {
2674 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"
, 2674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement"
") (" "No element?" ")"); do { *((volatile int*)__null) = 2674
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2675 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"
, 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aDocElement->GetParent()"
") (" "Not root content?" ")"); do { *((volatile int*)__null
) = 2675; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2676 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"
, 2676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()"
") (" "Not in a document?" ")"); do { *((volatile int*)__null
) = 2676; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2677 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"
, 2678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
") (" "Not the root of the document?" ")"); do { *((volatile
int*)__null) = 2678; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2678 "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"
, 2678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
") (" "Not the root of the document?" ")"); do { *((volatile
int*)__null) = 2678; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2679
2680 /*
2681 how the root frame hierarchy should look
2682
2683 Galley presentation, with scrolling:
2684
2685 ViewportFrame [fixed-cb]
2686 ScrollContainerFrame (if needed)
2687 nsCanvasFrame [abs-cb]
2688 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2689 nsTableWrapperFrame, nsPlaceholderFrame,
2690 nsFlexContainerFrame, nsGridContainerFrame)
2691
2692 Print presentation, non-XUL
2693
2694 ViewportFrame
2695 nsCanvasFrame
2696 nsPageSequenceFrame
2697 PrintedSheetFrame
2698 nsPageFrame
2699 nsPageContentFrame [fixed-cb]
2700 nsCanvasFrame [abs-cb]
2701 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2702 nsTableWrapperFrame, nsPlaceholderFrame,
2703 nsFlexContainerFrame,
2704 nsGridContainerFrame)
2705
2706 Print-preview presentation, non-XUL
2707
2708 ViewportFrame
2709 ScrollContainerFrame
2710 nsCanvasFrame
2711 nsPageSequenceFrame
2712 PrintedSheetFrame
2713 nsPageFrame
2714 nsPageContentFrame [fixed-cb]
2715 nsCanvasFrame [abs-cb]
2716 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2717 nsTableWrapperFrame,
2718 nsPlaceholderFrame,
2719 nsFlexContainerFrame,
2720 nsGridContainerFrame)
2721
2722 Print/print preview of XUL is not supported.
2723 [fixed-cb]: the default containing block for fixed-pos content
2724 [abs-cb]: the default containing block for abs-pos content
2725
2726 Meaning of nsCSSFrameConstructor fields:
2727 mRootElementFrame is "root element frame". This is the primary frame for
2728 the root element.
2729 mDocElementContainingBlock is the parent of mRootElementFrame
2730 (i.e. nsCanvasFrame)
2731 mPageSequenceFrame is the nsPageSequenceFrame, or null if there isn't
2732 one
2733 */
2734
2735 // --------- CREATE ROOT FRAME -------
2736
2737 // Create the root frame. The document element's frame is a child of the
2738 // root frame.
2739 //
2740 // The root frame serves two purposes:
2741 // - reserves space for any margins needed for the document element's frame
2742 // - renders the document element's background. This ensures the background
2743 // covers the entire canvas as specified by the CSS2 spec
2744
2745 nsPresContext* presContext = mPresShell->GetPresContext();
2746 const bool isPaginated = presContext->IsRootPaginatedDocument();
2747
2748 const bool isHTML = aDocElement->IsHTMLElement();
2749 const bool isXUL = !isHTML && aDocElement->IsXULElement();
2750
2751 const bool isScrollable = [&] {
2752 if (isPaginated) {
2753 return presContext->HasPaginatedScrolling();
2754 }
2755 // Never create scrollbars for XUL documents or top level XHTML documents
2756 // that disable scrolling.
2757 if (isXUL) {
2758 return false;
2759 }
2760 if (aDocElement->OwnerDoc()->ChromeRulesEnabled() &&
2761 aDocElement->AsElement()->AttrValueIs(
2762 kNameSpaceID_None, nsGkAtoms::scrolling, nsGkAtoms::_false,
2763 eCaseMatters)) {
2764 return false;
2765 }
2766 return true;
2767 }();
2768
2769 nsContainerFrame* viewportFrame =
2770 static_cast<nsContainerFrame*>(GetRootFrame());
2771 ComputedStyle* viewportPseudoStyle = viewportFrame->Style();
2772
2773 nsCanvasFrame* rootCanvasFrame =
2774 NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
2775 PseudoStyleType rootPseudo = PseudoStyleType::canvas;
2776 mCanvasFrame = rootCanvasFrame;
2777 mDocElementContainingBlock = rootCanvasFrame;
2778
2779 // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
2780
2781 // If the device supports scrolling (e.g., in galley mode on the screen and
2782 // for print-preview, but not when printing), then create a scroll frame that
2783 // will act as the scrolling mechanism for the viewport.
2784 // XXX Do we even need a viewport when printing to a printer?
2785
2786 // We no longer need to do overflow propagation here. It's taken care of
2787 // when we construct frames for the element whose overflow might be
2788 // propagated
2789 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"
, 2790); MOZ_PretendNoReturn(); } } while (0)
2790 "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"
, 2790); MOZ_PretendNoReturn(); } } while (0)
;
2791
2792 nsContainerFrame* newFrame = rootCanvasFrame;
2793 RefPtr<ComputedStyle> rootPseudoStyle;
2794 // we must create a state because if the scrollbars are GFX it needs the
2795 // state to build the scrollbar frames.
2796 nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
2797
2798 // Start off with the viewport as parent; we'll adjust it as needed.
2799 nsContainerFrame* parentFrame = viewportFrame;
2800
2801 ServoStyleSet* styleSet = mPresShell->StyleSet();
2802 // If paginated, make sure we don't put scrollbars in
2803 if (!isScrollable) {
2804 rootPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
2805 rootPseudo, viewportPseudoStyle);
2806 } else {
2807 rootPseudo = PseudoStyleType::scrolledCanvas;
2808
2809 // Build the frame. We give it the content we are wrapping which is the
2810 // document element, the root frame, the parent view port frame, and we
2811 // should get back the new frame and the scrollable view if one was
2812 // created.
2813
2814 // resolve a context for the scrollframe
2815 RefPtr<ComputedStyle> computedStyle =
2816 styleSet->ResolveInheritingAnonymousBoxStyle(
2817 PseudoStyleType::viewportScroll, viewportPseudoStyle);
2818
2819 // Note that the viewport scrollframe is always built with
2820 // overflow:auto style. This forces the scroll frame to create
2821 // anonymous content for both scrollbars. This is necessary even
2822 // if the HTML or BODY elements are overriding the viewport
2823 // scroll style to 'hidden' --- dynamic style changes might put
2824 // scrollbars back on the viewport and we don't want to have to
2825 // reframe the viewport to create the scrollbar content.
2826 newFrame = nullptr;
2827 rootPseudoStyle = BeginBuildingScrollContainerFrame(
2828 state, aDocElement, computedStyle, viewportFrame, rootPseudo, true,
2829 newFrame);
2830 parentFrame = newFrame;
2831 }
2832
2833 rootCanvasFrame->SetComputedStyleWithoutNotification(rootPseudoStyle);
2834 rootCanvasFrame->Init(aDocElement, parentFrame, nullptr);
2835
2836 if (isScrollable) {
2837 FinishBuildingScrollContainerFrame(parentFrame, rootCanvasFrame);
2838 }
2839
2840 if (isPaginated) {
2841 // Create a page sequence frame
2842 {
2843 RefPtr<ComputedStyle> pageSequenceStyle =
2844 styleSet->ResolveInheritingAnonymousBoxStyle(
2845 PseudoStyleType::pageSequence, viewportPseudoStyle);
2846 mPageSequenceFrame =
2847 NS_NewPageSequenceFrame(mPresShell, pageSequenceStyle);
2848 mPageSequenceFrame->Init(aDocElement, rootCanvasFrame, nullptr);
2849 SetInitialSingleChild(rootCanvasFrame, mPageSequenceFrame);
2850 }
2851
2852 // Create the first printed sheet frame, as the sole child (for now) of our
2853 // page sequence frame (mPageSequenceFrame).
2854 auto* printedSheetFrame =
2855 ConstructPrintedSheetFrame(mPresShell, mPageSequenceFrame, nullptr);
2856 SetInitialSingleChild(mPageSequenceFrame, printedSheetFrame);
2857
2858 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"
, 2859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2859; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2859 "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"
, 2859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2859; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2860
2861 // Create the first page, as the sole child (for now) of the printed sheet
2862 // frame that we just created.
2863 nsCanvasFrame* canvasFrame;
2864 nsContainerFrame* pageFrame =
2865 ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
2866 pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2867 SetInitialSingleChild(printedSheetFrame, pageFrame);
2868
2869 // The eventual parent of the document element frame.
2870 // XXX should this be set for every new page (in ConstructPageFrame)?
2871 mDocElementContainingBlock = canvasFrame;
2872 }
2873
2874 if (viewportFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
2875 SetInitialSingleChild(viewportFrame, newFrame);
2876 } else {
2877 viewportFrame->AppendFrames(FrameChildListID::Principal,
2878 nsFrameList(newFrame, newFrame));
2879 }
2880}
2881
2882void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
2883 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
2884 nsIContent* aDocElement, nsFrameList& aFrameList) {
2885 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"
, 2885); MOZ_PretendNoReturn(); } } while (0)
;
2886 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"
, 2886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRootElementFrame->GetContent() == aDocElement"
")"); do { *((volatile int*)__null) = 2886; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2887
2888 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
2889 GetAnonymousContent(aDocElement, aFrame, anonymousItems);
2890 if (anonymousItems.IsEmpty()) {
2891 return;
2892 }
2893
2894 AutoFrameConstructionItemList itemsToConstruct(this);
2895 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
2896 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
2897 itemsToConstruct, pageNameTracker);
2898 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
2899 /* aParentIsWrapperAnonBox = */ false,
2900 aFrameList);
2901}
2902
2903PrintedSheetFrame* nsCSSFrameConstructor::ConstructPrintedSheetFrame(
2904 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2905 nsIFrame* aPrevSheetFrame) {
2906 RefPtr<ComputedStyle> printedSheetPseudoStyle =
2907 aPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
2908 PseudoStyleType::printedSheet);
2909
2910 auto* printedSheetFrame =
2911 NS_NewPrintedSheetFrame(aPresShell, printedSheetPseudoStyle);
2912
2913 printedSheetFrame->Init(nullptr, aParentFrame, aPrevSheetFrame);
2914
2915 return printedSheetFrame;
2916}
2917
2918nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
2919 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2920 nsIFrame* aPrevPageFrame, nsCanvasFrame*& aCanvasFrame) {
2921 ServoStyleSet* styleSet = aPresShell->StyleSet();
2922
2923 RefPtr<ComputedStyle> pagePseudoStyle =
2924 styleSet->ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType::page);
2925
2926 nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
2927
2928 // Initialize the page frame and force it to have a view. This makes printing
2929 // of the pages easier and faster.
2930 pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
2931
2932 RefPtr<const nsAtom> pageName;
2933 if (mNextPageContentFramePageName) {
2934 pageName = mNextPageContentFramePageName.forget();
2935 } else if (aPrevPageFrame) {
2936 pageName = aPrevPageFrame->ComputePageValue();
2937 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"
, 2938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2938 "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"
, 2938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2939 }
2940 RefPtr<ComputedStyle> pageContentPseudoStyle =
2941 styleSet->ResolvePageContentStyle(pageName,
2942 StylePagePseudoClassFlags::NONE);
2943
2944 nsContainerFrame* pageContentFrame = NS_NewPageContentFrame(
2945 aPresShell, pageContentPseudoStyle, pageName.forget());
2946
2947 nsPageContentFrame* prevPageContentFrame = nullptr;
2948 if (aPrevPageFrame) {
2949 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"
, 2949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevPageFrame->IsPageFrame()"
")"); do { *((volatile int*)__null) = 2949; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2950 prevPageContentFrame =
2951 static_cast<nsPageFrame*>(aPrevPageFrame)->PageContentFrame();
2952 }
2953 pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
2954 if (!prevPageContentFrame) {
2955 // The canvas is an inheriting anon box, so needs to be "owned" by the page
2956 // content.
2957 pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2958 }
2959 SetInitialSingleChild(pageFrame, pageContentFrame);
2960 // Make it an absolute container for fixed-pos elements
2961 pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2962 pageContentFrame->MarkAsAbsoluteContainingBlock();
2963
2964 RefPtr<ComputedStyle> canvasPseudoStyle =
2965 styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::canvas,
2966 pageContentPseudoStyle);
2967
2968 aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
2969
2970 nsIFrame* prevCanvasFrame = nullptr;
2971 if (prevPageContentFrame) {
2972 prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
2973 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"
, 2973); MOZ_PretendNoReturn(); } } while (0)
;
2974 }
2975 aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
2976 SetInitialSingleChild(pageContentFrame, aCanvasFrame);
2977 return pageFrame;
2978}
2979
2980/* static */
2981nsIFrame* nsCSSFrameConstructor::CreatePlaceholderFrameFor(
2982 PresShell* aPresShell, nsIContent* aContent, nsIFrame* aFrame,
2983 nsContainerFrame* aParentFrame, nsIFrame* aPrevInFlow,
2984 nsFrameState aTypeBit) {
2985 RefPtr<ComputedStyle> placeholderStyle =
2986 aPresShell->StyleSet()->ResolveStyleForPlaceholder();
2987
2988 // The placeholder frame gets a pseudo style.
2989 nsPlaceholderFrame* placeholderFrame =
2990 NS_NewPlaceholderFrame(aPresShell, placeholderStyle, aTypeBit);
2991
2992 placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
2993
2994 // Associate the placeholder/out-of-flow with each other.
2995 placeholderFrame->SetOutOfFlowFrame(aFrame);
2996 aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame);
2997
2998 aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
2999
3000 return placeholderFrame;
3001}
3002
3003// Clears any lazy bits set in the range [aStartContent, aEndContent). If
3004// aEndContent is null, that means to clear bits in all siblings starting with
3005// aStartContent. aStartContent must not be null unless aEndContent is also
3006// null. We do this so that when new children are inserted under elements whose
3007// frame is a leaf the new children don't cause us to try to construct frames
3008// for the existing children again.
3009static inline void ClearLazyBits(nsIContent* aStartContent,
3010 nsIContent* aEndContent) {
3011 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"
, 3012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3012; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3012 "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"
, 3012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3012; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3013
3014 for (nsIContent* cur = aStartContent; cur != aEndContent;
3015 cur = cur->GetNextSibling()) {
3016 cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
3017 }
3018}
3019
3020/* static */
3021const nsCSSFrameConstructor::FrameConstructionData*
3022nsCSSFrameConstructor::FindSelectData(const Element& aElement,
3023 ComputedStyle& aStyle) {
3024 // Construct a frame-based listbox or combobox
3025 const auto* sel = dom::HTMLSelectElement::FromNode(aElement);
3026 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"
, 3026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sel" ")"); do
{ *((volatile int*)__null) = 3026; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3027 if (sel->IsCombobox()) {
3028 static constexpr FrameConstructionData sComboboxData{
3029 ToCreationFunc(NS_NewComboboxControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewComboboxControlFrame(aPs, aStyle); }
, 0,
3030 PseudoStyleType::buttonContent};
3031 return &sComboboxData;
3032 }
3033 // FIXME: Can we simplify this to avoid needing ConstructListboxSelectFrame,
3034 // and reuse ConstructScrollableBlock or so?
3035 static constexpr FrameConstructionData sListBoxData{
3036 &nsCSSFrameConstructor::ConstructListBoxSelectFrame};
3037 return &sListBoxData;
3038}
3039
3040nsIFrame* nsCSSFrameConstructor::ConstructListBoxSelectFrame(
3041 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3042 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3043 nsFrameList& aFrameList) {
3044 nsIContent* const content = aItem.mContent;
3045 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3046
3047 // Listbox, not combobox
3048 nsContainerFrame* listFrame =
3049 NS_NewListControlFrame(mPresShell, computedStyle);
3050
3051 nsContainerFrame* scrolledFrame =
3052 NS_NewSelectsAreaFrame(mPresShell, computedStyle);
3053
3054 // ******* this code stolen from Initialze ScrollFrame ********
3055 // please adjust this code to use BuildScrollFrame.
3056
3057 InitializeListboxSelect(aState, listFrame, scrolledFrame, content,
3058 aParentFrame, computedStyle, aFrameList);
3059
3060 return listFrame;
3061}
3062
3063void nsCSSFrameConstructor::InitializeListboxSelect(
3064 nsFrameConstructorState& aState, nsContainerFrame* scrollFrame,
3065 nsContainerFrame* scrolledFrame, nsIContent* aContent,
3066 nsContainerFrame* aParentFrame, ComputedStyle* aComputedStyle,
3067 nsFrameList& aFrameList) {
3068 // Initialize it
3069 nsContainerFrame* geometricParent =
3070 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
3071
3072 // We don't call InitAndRestoreFrame for scrollFrame because we can only
3073 // restore the frame state after its parts have been created (in particular,
3074 // the scrollable view). So we have to split Init and Restore.
3075
3076 scrollFrame->Init(aContent, geometricParent, nullptr);
3077 aState.AddChild(scrollFrame, aFrameList, aContent, aParentFrame);
3078 BuildScrollContainerFrame(aState, aContent, aComputedStyle, scrolledFrame,
3079 geometricParent, scrollFrame);
3080 if (aState.mFrameState) {
3081 // Restore frame state for the scroll frame
3082 RestoreFrameStateFor(scrollFrame, aState.mFrameState);
3083 }
3084
3085 nsFrameConstructorSaveState floatSaveState;
3086 aState.MaybePushFloatContainingBlock(scrolledFrame, floatSaveState);
3087
3088 // Process children
3089 nsFrameList childList;
3090
3091 ProcessChildren(aState, aContent, aComputedStyle, scrolledFrame, false,
3092 childList, false);
3093
3094 // Set the scrolled frame's initial child lists
3095 scrolledFrame->SetInitialChildList(FrameChildListID::Principal,
3096 std::move(childList));
3097}
3098
3099nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
3100 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3101 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3102 nsFrameList& aFrameList) {
3103 AutoRestore<bool> savedHasRenderedLegend(aState.mHasRenderedLegend);
3104 aState.mHasRenderedLegend = false;
3105 nsIContent* const content = aItem.mContent;
3106 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3107
3108 nsContainerFrame* fieldsetFrame =
3109 NS_NewFieldSetFrame(mPresShell, computedStyle);
3110
3111 // Initialize it
3112 InitAndRestoreFrame(aState, content,
3113 aState.GetGeometricParent(*aStyleDisplay, aParentFrame),
3114 fieldsetFrame);
3115
3116 fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3117
3118 // Resolve style and initialize the frame
3119 RefPtr<ComputedStyle> fieldsetContentStyle =
3120 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3121 PseudoStyleType::fieldsetContent, computedStyle);
3122
3123 const nsStyleDisplay* fieldsetContentDisplay =
3124 fieldsetContentStyle->StyleDisplay();
3125 const bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
3126 nsContainerFrame* scrollFrame = nullptr;
3127 if (isScrollable) {
3128 fieldsetContentStyle = BeginBuildingScrollContainerFrame(
3129 aState, content, fieldsetContentStyle, fieldsetFrame,
3130 PseudoStyleType::scrolledContent, false, scrollFrame);
3131 }
3132
3133 // Create the inner ::-moz-fieldset-content frame.
3134 nsContainerFrame* contentFrameTop;
3135 nsContainerFrame* contentFrame;
3136 auto* parent = scrollFrame ? scrollFrame : fieldsetFrame;
3137 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"
, 3138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3138 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"
, 3138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3139 switch (fieldsetContentDisplay->DisplayInside()) {
3140 case StyleDisplayInside::Flex:
3141 contentFrame = NS_NewFlexContainerFrame(mPresShell, fieldsetContentStyle);
3142 InitAndRestoreFrame(aState, content, parent, contentFrame);
3143 contentFrameTop = contentFrame;
3144 break;
3145 case StyleDisplayInside::Grid:
3146 contentFrame = NS_NewGridContainerFrame(mPresShell, fieldsetContentStyle);
3147 InitAndRestoreFrame(aState, content, parent, contentFrame);
3148 contentFrameTop = contentFrame;
3149 break;
3150 default: {
3151 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"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3152 "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"
, 3152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3153
3154 contentFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle);
3155 if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
3156 contentFrameTop = BeginBuildingColumns(
3157 aState, content, parent, contentFrame, fieldsetContentStyle);
3158 } else {
3159 // No need to create column container. Initialize content frame.
3160 InitAndRestoreFrame(aState, content, parent, contentFrame);
3161 contentFrameTop = contentFrame;
3162 }
3163
3164 break;
3165 }
3166 }
3167
3168 aState.AddChild(fieldsetFrame, aFrameList, content, aParentFrame);
3169
3170 // Process children
3171 nsFrameConstructorSaveState absoluteSaveState;
3172 nsFrameList childList;
3173
3174 contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3175 if (fieldsetFrame->IsAbsPosContainingBlock()) {
3176 aState.PushAbsoluteContainingBlock(contentFrameTop, fieldsetFrame,
3177 absoluteSaveState);
3178 }
3179
3180 nsFrameConstructorSaveState floatSaveState;
3181 aState.MaybePushFloatContainingBlock(contentFrame, floatSaveState);
3182
3183 ProcessChildren(aState, content, computedStyle, contentFrame, true, childList,
3184 true);
3185 nsFrameList fieldsetKids;
3186 fieldsetKids.AppendFrame(nullptr,
3187 scrollFrame ? scrollFrame : contentFrameTop);
3188
3189 if (!MayNeedToCreateColumnSpanSiblings(contentFrame, childList)) {
3190 // Set the inner frame's initial child lists.
3191 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3192 std::move(childList));
3193 } else {
3194 // Extract any initial non-column-span kids, and put them in inner frame's
3195 // child list.
3196 nsFrameList initialNonColumnSpanKids =
3197 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3198 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3199 std::move(initialNonColumnSpanKids));
3200
3201 if (childList.NotEmpty()) {
3202 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3203 aState, contentFrame, childList,
3204 // Column content should never be a absolute/fixed positioned
3205 // containing block. Pass nullptr as aPositionedFrame.
3206 nullptr);
3207 FinishBuildingColumns(aState, contentFrameTop, contentFrame,
3208 columnSpanSiblings);
3209 }
3210 }
3211
3212 if (isScrollable) {
3213 FinishBuildingScrollContainerFrame(scrollFrame, contentFrameTop);
3214 }
3215
3216 // We use AppendFrames here because the rendered legend will already
3217 // be present in the principal child list if it exists.
3218 fieldsetFrame->AppendFrames(FrameChildListID::NoReflowPrincipal,
3219 std::move(fieldsetKids));
3220
3221 return fieldsetFrame;
3222}
3223
3224const nsCSSFrameConstructor::FrameConstructionData*
3225nsCSSFrameConstructor::FindDetailsData(const Element& aElement,
3226 ComputedStyle& aStyle) {
3227 if (!StaticPrefs::layout_details_force_block_layout()) {
3228 return nullptr;
3229 }
3230 static constexpr FrameConstructionData sBlockData[2] = {
3231 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
3232 {&nsCSSFrameConstructor::ConstructScrollableBlock},
3233 };
3234 return &sBlockData[aStyle.StyleDisplay()->IsScrollableOverflow()];
3235}
3236
3237nsIFrame* nsCSSFrameConstructor::ConstructBlockRubyFrame(
3238 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3239 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3240 nsFrameList& aFrameList) {
3241 nsIContent* const content = aItem.mContent;
3242 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3243
3244 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, computedStyle);
3245 nsContainerFrame* newFrame = blockFrame;
3246 nsContainerFrame* geometricParent =
3247 aState.GetGeometricParent(*aStyleDisplay, aParentFrame);
3248 AutoFrameConstructionPageName pageNameTracker(aState, blockFrame);
3249 if ((aItem.mFCData->mBits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3250 aStyleDisplay->IsScrollableOverflow()) {
3251 nsContainerFrame* scrollframe = nullptr;
3252 BuildScrollContainerFrame(aState, content, computedStyle, blockFrame,
3253 geometricParent, scrollframe);
3254 newFrame = scrollframe;
3255 } else {
3256 InitAndRestoreFrame(aState, content, geometricParent, blockFrame);
3257 }
3258
3259 RefPtr<ComputedStyle> rubyStyle =
3260 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3261 PseudoStyleType::blockRubyContent, computedStyle);
3262 nsContainerFrame* rubyFrame = NS_NewRubyFrame(mPresShell, rubyStyle);
3263 InitAndRestoreFrame(aState, content, blockFrame, rubyFrame);
3264 SetInitialSingleChild(blockFrame, rubyFrame);
3265 blockFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3266
3267 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
3268
3269 if (!mRootElementFrame) {
3270 mRootElementFrame = newFrame;
3271 }
3272
3273 nsFrameConstructorSaveState absoluteSaveState;
3274 blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3275 if (newFrame->IsAbsPosContainingBlock()) {
3276 aState.PushAbsoluteContainingBlock(blockFrame, blockFrame,
3277 absoluteSaveState);
3278 }
3279 nsFrameConstructorSaveState floatSaveState;
3280 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
3281
3282 nsFrameList childList;
3283 ProcessChildren(aState, content, rubyStyle, rubyFrame, true, childList, false,
3284 nullptr);
3285 rubyFrame->SetInitialChildList(FrameChildListID::Principal,
3286 std::move(childList));
3287
3288 return newFrame;
3289}
3290
3291static nsIFrame* FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame) {
3292 for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
3293 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"
, 3294); MOZ_PretendNoReturn(); } } while (0)
3294 "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"
, 3294); MOZ_PretendNoReturn(); } } while (0)
;
3295 auto pseudo = f->Style()->GetPseudoType();
3296 if (pseudo == PseudoStyleType::before || pseudo == PseudoStyleType::after ||
3297 pseudo == PseudoStyleType::marker)
3298 return f;
3299 }
3300 return nullptr;
3301}
3302
3303/* static */
3304const nsCSSFrameConstructor::FrameConstructionData*
3305nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
3306 nsIFrame* aParentFrame) {
3307 if (aParentFrame && IsFrameForSVG(aParentFrame)) {
3308 if (!aParentFrame->IsInSVGTextSubtree()) {
3309 return nullptr;
3310 }
3311
3312 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
3313 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
3314 // really know how to deal with it. This kinda sucks. :(
3315 if (aParentFrame->GetContent() != aTextContent.GetParent()) {
3316 return nullptr;
3317 }
3318
3319 static constexpr FrameConstructionData sSVGTextData(
3320 NS_NewTextFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_SVG_TEXT0x80000);
3321 return &sSVGTextData;
3322 }
3323
3324 static constexpr FrameConstructionData sTextData(NS_NewTextFrame,
3325 FCDATA_IS_LINE_PARTICIPANT0x2000);
3326 return &sTextData;
3327}
3328
3329void nsCSSFrameConstructor::ConstructTextFrame(
3330 const FrameConstructionData* aData, nsFrameConstructorState& aState,
3331 nsIContent* aContent, nsContainerFrame* aParentFrame,
3332 ComputedStyle* aComputedStyle, nsFrameList& aFrameList) {
3333 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"
, 3333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aData" ") ("
"Must have frame construction data" ")"); do { *((volatile int
*)__null) = 3333; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3334
3335 nsIFrame* newFrame =
3336 (*aData->mFunc.mCreationFunc)(mPresShell, aComputedStyle);
3337
3338 InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
3339
3340 // We never need to create a view for a text frame.
3341
3342 if (newFrame->IsGeneratedContentFrame()) {
3343 UniquePtr<nsGenConInitializer> initializer(
3344 static_cast<nsGenConInitializer*>(
3345 aContent->TakeProperty(nsGkAtoms::genConInitializerProperty)));
3346 if (initializer) {
3347 if (initializer->mNode.release()->InitTextFrame(
3348 initializer->mList,
3349 FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
3350 (this->*(initializer->mDirtyAll))();
3351 }
3352 }
3353 }
3354
3355 // Add the newly constructed frame to the flow
3356 aFrameList.AppendFrame(nullptr, newFrame);
3357
3358 if (!aState.mCreatingExtraFrames || (aContent->IsInNativeAnonymousSubtree() &&
3359 !aContent->GetPrimaryFrame())) {
3360 aContent->SetPrimaryFrame(newFrame);
3361 }
3362}
3363
3364/* static */
3365const nsCSSFrameConstructor::FrameConstructionData*
3366nsCSSFrameConstructor::FindDataByInt(int32_t aInt, const Element& aElement,
3367 ComputedStyle& aComputedStyle,
3368 const FrameConstructionDataByInt* aDataPtr,
3369 uint32_t aDataLength) {
3370 for (const FrameConstructionDataByInt *curData = aDataPtr,
3371 *endData = aDataPtr + aDataLength;
3372 curData != endData; ++curData) {
3373 if (curData->mInt == aInt) {
3374 const FrameConstructionData* data = &curData->mData;
3375 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3376 return data->mFunc.mDataGetter(aElement, aComputedStyle);
3377 }
3378
3379 return data;
3380 }
3381 }
3382
3383 return nullptr;
3384}
3385
3386/* static */
3387const nsCSSFrameConstructor::FrameConstructionData*
3388nsCSSFrameConstructor::FindDataByTag(const Element& aElement,
3389 ComputedStyle& aStyle,
3390 const FrameConstructionDataByTag* aDataPtr,
3391 uint32_t aDataLength) {
3392 const nsAtom* tag = aElement.NodeInfo()->NameAtom();
3393 for (const FrameConstructionDataByTag *curData = aDataPtr,
3394 *endData = aDataPtr + aDataLength;
3395 curData != endData; ++curData) {
3396 if (curData->mTag == tag) {
3397 const FrameConstructionData* data = &curData->mData;
3398 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3399 return data->mFunc.mDataGetter(aElement, aStyle);
3400 }
3401
3402 return data;
3403 }
3404 }
3405
3406 return nullptr;
3407}
3408
3409#define SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40) FrameConstructionData(nullptr, FCDATA_SUPPRESS_FRAME0x40)
3410#define SIMPLE_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3411 {int32_t(_int), FrameConstructionData(_func)}
3412#define SIMPLE_INT_CHAIN(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3413 {int32_t(_int), FrameConstructionData(_func)}
3414#define COMPLEX_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3415 {int32_t(_int), FrameConstructionData(_func)}
3416
3417#define SIMPLE_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3418 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3419#define SIMPLE_TAG_CHAIN(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3420 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3421#define COMPLEX_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3422 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3423
3424static nsFieldSetFrame* GetFieldSetFrameFor(nsIFrame* aFrame) {
3425 auto pseudo = aFrame->Style()->GetPseudoType();
3426 if (pseudo == PseudoStyleType::fieldsetContent ||
3427 pseudo == PseudoStyleType::scrolledContent ||
3428 pseudo == PseudoStyleType::columnSet ||
3429 pseudo == PseudoStyleType::columnContent) {
3430 return GetFieldSetFrameFor(aFrame->GetParent());
3431 }
3432 return do_QueryFrame(aFrame);
3433}
3434
3435/* static */
3436const nsCSSFrameConstructor::FrameConstructionData*
3437nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
3438 nsIFrame* aParentFrame,
3439 ComputedStyle& aStyle) {
3440 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"
, 3440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsHTMLElement()"
")"); do { *((volatile int*)__null) = 3440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3441 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"
, 3445); MOZ_PretendNoReturn(); } } while (0)
3442 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"
, 3445); MOZ_PretendNoReturn(); } } while (0)
3443 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"
, 3445); MOZ_PretendNoReturn(); } } while (0)
3444 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"
, 3445); MOZ_PretendNoReturn(); } } while (0)
3445 "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"
, 3445); MOZ_PretendNoReturn(); } } while (0)
;
3446
3447 if (aElement.IsInNativeAnonymousSubtree() &&
3448 aElement.NodeInfo()->NameAtom() == nsGkAtoms::label && aParentFrame) {
3449 if (aParentFrame->IsFileControlFrame()) {
3450 static constexpr FrameConstructionData sFileLabelData(
3451 NS_NewFileControlLabelFrame);
3452 return &sFileLabelData;
3453 }
3454 if (aParentFrame->GetParent() &&
3455 aParentFrame->GetParent()->IsComboboxControlFrame()) {
3456 static constexpr FrameConstructionData sComboboxLabelData(
3457 NS_NewComboboxLabelFrame);
3458 return &sComboboxLabelData;
3459 }
3460 }
3461
3462 static constexpr FrameConstructionDataByTag sHTMLData[] = {
3463 SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData){nsGkAtoms::img, FrameConstructionData(nsCSSFrameConstructor::
FindImgData)}
,
3464 SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,{nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
3465 nsCSSFrameConstructor::FindGeneratedImageData){nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
,
3466 {nsGkAtoms::br,
3467 {NS_NewBRFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_LINE_BREAK0x4000}},
3468 SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame){nsGkAtoms::wbr, FrameConstructionData(NS_NewWBRFrame)},
3469 SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData){nsGkAtoms::input, FrameConstructionData(nsCSSFrameConstructor
::FindInputData)}
,
3470 SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame){nsGkAtoms::textarea, FrameConstructionData(NS_NewTextControlFrame
)}
,
3471 SIMPLE_TAG_CHAIN(select, nsCSSFrameConstructor::FindSelectData){nsGkAtoms::select, FrameConstructionData(nsCSSFrameConstructor
::FindSelectData)}
,
3472 SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::object, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3473 SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::embed, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3474 COMPLEX_TAG_CREATE(fieldset,{nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
3475 &nsCSSFrameConstructor::ConstructFieldSetFrame){nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
,
3476 SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame){nsGkAtoms::frameset, FrameConstructionData(NS_NewHTMLFramesetFrame
)}
,
3477 SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
3478 {nsGkAtoms::button,
3479 {ToCreationFunc(NS_NewHTMLButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewHTMLButtonControlFrame(aPs, aStyle); }
,
3480 FCDATA_ALLOW_BLOCK_STYLES0x8000 | FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000,
3481 PseudoStyleType::buttonContent}},
3482 SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData){nsGkAtoms::canvas, FrameConstructionData(nsCSSFrameConstructor
::FindCanvasData)}
,
3483 SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame){nsGkAtoms::video, FrameConstructionData(NS_NewHTMLVideoFrame
)}
,
3484 SIMPLE_TAG_CREATE(audio, NS_NewHTMLAudioFrame){nsGkAtoms::audio, FrameConstructionData(NS_NewHTMLAudioFrame
)}
,
3485 SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame){nsGkAtoms::progress, FrameConstructionData(NS_NewProgressFrame
)}
,
3486 SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame){nsGkAtoms::meter, FrameConstructionData(NS_NewMeterFrame)},
3487 SIMPLE_TAG_CHAIN(details, nsCSSFrameConstructor::FindDetailsData){nsGkAtoms::details, FrameConstructionData(nsCSSFrameConstructor
::FindDetailsData)}
,
3488 };
3489
3490 return FindDataByTag(aElement, aStyle, sHTMLData, ArrayLength(sHTMLData));
3491}
3492
3493/* static */
3494const nsCSSFrameConstructor::FrameConstructionData*
3495nsCSSFrameConstructor::FindGeneratedImageData(const Element& aElement,
3496 ComputedStyle&) {
3497 if (!aElement.IsInNativeAnonymousSubtree()) {
3498 return nullptr;
3499 }
3500
3501 auto& generatedContent = static_cast<const GeneratedImageContent&>(aElement);
3502 if (generatedContent.IsForListStyleImageMarker()) {
3503 static constexpr FrameConstructionData sImgData(
3504 NS_NewImageFrameForListStyleImage);
3505 return &sImgData;
3506 }
3507
3508 static constexpr FrameConstructionData sImgData(
3509 NS_NewImageFrameForGeneratedContentIndex);
3510 return &sImgData;
3511}
3512
3513/* static */
3514const nsCSSFrameConstructor::FrameConstructionData*
3515nsCSSFrameConstructor::FindImgData(const Element& aElement,
3516 ComputedStyle& aStyle) {
3517 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3518 nsImageFrame::ImageFrameType::ForElementRequest) {
3519 // content: url gets handled by the generic code-path.
3520 return nullptr;
3521 }
3522
3523 static constexpr FrameConstructionData sImgData(NS_NewImageFrame);
3524 return &sImgData;
3525}
3526
3527/* static */
3528const nsCSSFrameConstructor::FrameConstructionData*
3529nsCSSFrameConstructor::FindImgControlData(const Element& aElement,
3530 ComputedStyle& aStyle) {
3531 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3532 nsImageFrame::ImageFrameType::ForElementRequest) {
3533 return nullptr;
3534 }
3535
3536 static constexpr FrameConstructionData sImgControlData(
3537 NS_NewImageControlFrame);
3538 return &sImgControlData;
3539}
3540
3541/* static */
3542const nsCSSFrameConstructor::FrameConstructionData*
3543nsCSSFrameConstructor::FindSearchControlData(const Element& aElement,
3544 ComputedStyle& aStyle) {
3545 if (StaticPrefs::layout_forms_input_type_search_enabled()) {
3546 static constexpr FrameConstructionData sSearchControlData(
3547 NS_NewSearchControlFrame);
3548 return &sSearchControlData;
3549 }
3550
3551 static constexpr FrameConstructionData sTextControlData(
3552 NS_NewTextControlFrame);
3553 return &sTextControlData;
3554}
3555
3556/* static */
3557const nsCSSFrameConstructor::FrameConstructionData*
3558nsCSSFrameConstructor::FindInputData(const Element& aElement,
3559 ComputedStyle& aStyle) {
3560 static constexpr FrameConstructionDataByInt sInputData[] = {
3561 SIMPLE_INT_CREATE(FormControlType::InputCheckbox,{int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3562 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3563 SIMPLE_INT_CREATE(FormControlType::InputRadio,{int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3564 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3565 SIMPLE_INT_CREATE(FormControlType::InputFile, NS_NewFileControlFrame){int32_t(FormControlType::InputFile), FrameConstructionData(NS_NewFileControlFrame
)}
,
3566 SIMPLE_INT_CHAIN(FormControlType::InputImage,{int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
3567 nsCSSFrameConstructor::FindImgControlData){int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
,
3568 SIMPLE_INT_CREATE(FormControlType::InputEmail, NS_NewTextControlFrame){int32_t(FormControlType::InputEmail), FrameConstructionData(
NS_NewTextControlFrame)}
,
3569 SIMPLE_INT_CREATE(FormControlType::InputText, NS_NewTextControlFrame){int32_t(FormControlType::InputText), FrameConstructionData(NS_NewTextControlFrame
)}
,
3570 SIMPLE_INT_CREATE(FormControlType::InputTel, NS_NewTextControlFrame){int32_t(FormControlType::InputTel), FrameConstructionData(NS_NewTextControlFrame
)}
,
3571 SIMPLE_INT_CREATE(FormControlType::InputUrl, NS_NewTextControlFrame){int32_t(FormControlType::InputUrl), FrameConstructionData(NS_NewTextControlFrame
)}
,
3572 SIMPLE_INT_CREATE(FormControlType::InputRange, NS_NewRangeFrame){int32_t(FormControlType::InputRange), FrameConstructionData(
NS_NewRangeFrame)}
,
3573 SIMPLE_INT_CREATE(FormControlType::InputPassword, NS_NewTextControlFrame){int32_t(FormControlType::InputPassword), FrameConstructionData
(NS_NewTextControlFrame)}
,
3574 {int32_t(FormControlType::InputColor),
3575 {NS_NewColorControlFrame, 0, PseudoStyleType::buttonContent}},
3576
3577 SIMPLE_INT_CHAIN(FormControlType::InputSearch,{int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
3578 nsCSSFrameConstructor::FindSearchControlData){int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
,
3579 SIMPLE_INT_CREATE(FormControlType::InputNumber, NS_NewNumberControlFrame){int32_t(FormControlType::InputNumber), FrameConstructionData
(NS_NewNumberControlFrame)}
,
3580 SIMPLE_INT_CREATE(FormControlType::InputTime, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputTime), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3581 SIMPLE_INT_CREATE(FormControlType::InputDate, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDate), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3582 SIMPLE_INT_CREATE(FormControlType::InputDatetimeLocal,{int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
3583 NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
,
3584 // TODO: this is temporary until a frame is written: bug 888320
3585 SIMPLE_INT_CREATE(FormControlType::InputMonth, NS_NewTextControlFrame){int32_t(FormControlType::InputMonth), FrameConstructionData(
NS_NewTextControlFrame)}
,
3586 // TODO: this is temporary until a frame is written: bug 888320
3587 SIMPLE_INT_CREATE(FormControlType::InputWeek, NS_NewTextControlFrame){int32_t(FormControlType::InputWeek), FrameConstructionData(NS_NewTextControlFrame
)}
,
3588 {int32_t(FormControlType::InputSubmit),
3589 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3590 PseudoStyleType::buttonContent}},
3591 {int32_t(FormControlType::InputReset),
3592 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3593 PseudoStyleType::buttonContent}},
3594 {int32_t(FormControlType::InputButton),
3595 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3596 PseudoStyleType::buttonContent}}
3597 // Keeping hidden inputs out of here on purpose for so they get frames by
3598 // display (in practice, none).
3599 };
3600
3601 auto controlType = HTMLInputElement::FromNode(aElement)->ControlType();
3602
3603 // radio and checkbox inputs with appearance:none should be constructed
3604 // by display type. (Note that we're not checking that appearance is
3605 // not (respectively) StyleAppearance::Radio and StyleAppearance::Checkbox.)
3606 if ((controlType == FormControlType::InputCheckbox ||
3607 controlType == FormControlType::InputRadio) &&
3608 !aStyle.StyleDisplay()->HasAppearance()) {
3609 return nullptr;
3610 }
3611
3612 return FindDataByInt(int32_t(controlType), aElement, aStyle, sInputData,
3613 ArrayLength(sInputData));
3614}
3615
3616/* static */
3617const nsCSSFrameConstructor::FrameConstructionData*
3618nsCSSFrameConstructor::FindObjectData(const Element& aElement,
3619 ComputedStyle& aStyle) {
3620 uint32_t type;
3621 nsCOMPtr<nsIObjectLoadingContent> objContent =
3622 do_QueryInterface(const_cast<Element*>(&aElement));
3623 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"
, 3625); MOZ_PretendNoReturn(); } } while (0)
3624 "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"
, 3625); MOZ_PretendNoReturn(); } } while (0)
3625 "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"
, 3625); MOZ_PretendNoReturn(); } } while (0)
;
3626 objContent->GetDisplayedType(&type);
3627
3628 static constexpr FrameConstructionDataByInt sObjectData[] = {
3629 // TODO(emilio): Can we remove the NS_NewEmptyFrame case and just use a
3630 // subdocument frame here?
3631 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,{int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
3632 NS_NewEmptyFrame){int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
,
3633 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,{int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
3634 NS_NewSubDocumentFrame){int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
,
3635 // Nothing for TYPE_FALLBACK so we'll construct frames by display there
3636 };
3637
3638 return FindDataByInt((int32_t)type, aElement, aStyle, sObjectData,
3639 ArrayLength(sObjectData));
3640}
3641
3642/* static */
3643const nsCSSFrameConstructor::FrameConstructionData*
3644nsCSSFrameConstructor::FindCanvasData(const Element& aElement,
3645 ComputedStyle& aStyle) {
3646 // We want to check whether script is enabled on the document that
3647 // could be painting to the canvas. That's the owner document of
3648 // the canvas, except when the owner document is a static document,
3649 // in which case it's the original document it was cloned from.
3650 Document* doc = aElement.OwnerDoc();
3651 if (doc->IsStaticDocument()) {
3652 doc = doc->GetOriginalDocument();
3653 }
3654 if (!doc->IsScriptEnabled()) {
3655 return nullptr;
3656 }
3657
3658 static constexpr FrameConstructionData sCanvasData(
3659 NS_NewHTMLCanvasFrame, 0, PseudoStyleType::htmlCanvasContent);
3660 return &sCanvasData;
3661}
3662
3663static MOZ_NEVER_INLINE__attribute__((noinline)) void DestroyFramesInList(PresShell* aPs,
3664 nsFrameList& aList) {
3665 nsIFrame::DestroyContext context(aPs);
3666 aList.DestroyFrames(context);
3667}
3668
3669void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
3670 FrameConstructionItem& aItem, nsFrameConstructorState& aState,
3671 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
3672 const FrameConstructionData* data = aItem.mFCData;
3673 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"
, 3673); MOZ_PretendNoReturn(); } } while (0)
;
3674
3675 uint32_t bits = data->mBits;
3676
3677 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"
, 3678); MOZ_PretendNoReturn(); } } while (0)
3678 "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"
, 3678); MOZ_PretendNoReturn(); } } while (0)
;
3679
3680 // Some sets of bits are not compatible with each other
3681#define CHECK_ONLY_ONE_BIT(_bit1, _bit2) \
3682 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"
, 3683); MOZ_PretendNoReturn(); } } while (0)
3683 "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"
, 3683); MOZ_PretendNoReturn(); } } while (0)
3684 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3685 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10);
3686 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
3687 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_IS_POPUP0x100);
3688 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_SKIP_ABSPOS_PUSH0x200);
3689 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3690 FCDATA_DISALLOW_GENERATED_CONTENT0x400);
3691 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_ALLOW_BLOCK_STYLES0x8000);
3692 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3693 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3694 CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS0x20,
3695 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3696#undef CHECK_ONLY_ONE_BIT
3697 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"
, 3699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3698 !(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"
, 3699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3699 "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"
, 3699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3700 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"
, 3702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3701 (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"
, 3702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3702 "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"
, 3702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3703
3704 // Don't create a subdocument frame for iframes if we're creating extra frames
3705 if (aState.mCreatingExtraFrames &&
3706 aItem.mContent->IsHTMLElement(nsGkAtoms::iframe)) {
3707 return;
3708 }
3709
3710 nsIContent* const content = aItem.mContent;
3711 nsIFrame* newFrame;
3712 nsIFrame* primaryFrame;
3713 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3714 const nsStyleDisplay* display = computedStyle->StyleDisplay();
3715 if (bits & FCDATA_FUNC_IS_FULL_CTOR0x4) {
3716 newFrame = (this->*(data->mFunc.mFullConstructor))(
3717 aState, aItem, aParentFrame, display, aFrameList);
3718 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"
, 3718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newFrame" ") ("
"Full constructor failed" ")"); do { *((volatile int*)__null
) = 3718; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3719 primaryFrame = newFrame;
3720 } else {
3721 newFrame = (*data->mFunc.mCreationFunc)(mPresShell, computedStyle);
3722
3723 const bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8);
3724 const bool isPopup = aItem.mIsPopup;
3725
3726 nsContainerFrame* geometricParent =
3727 (isPopup || allowOutOfFlow)
3728 ? aState.GetGeometricParent(*display, aParentFrame)
3729 : aParentFrame;
3730
3731 // In the non-scrollframe case, primaryFrame and newFrame are equal; in the
3732 // scrollframe case, newFrame is the scrolled frame while primaryFrame is
3733 // the scrollframe.
3734 if ((bits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3735 display->IsScrollableOverflow()) {
3736 nsContainerFrame* scrollframe = nullptr;
3737 BuildScrollContainerFrame(aState, content, computedStyle, newFrame,
3738 geometricParent, scrollframe);
3739 primaryFrame = scrollframe;
3740 } else {
3741 InitAndRestoreFrame(aState, content, geometricParent, newFrame);
3742 primaryFrame = newFrame;
3743 }
3744
3745 // If we need to create a block formatting context to wrap our
3746 // kids, do it now.
3747 nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
3748 nsIFrame* maybeAbsoluteContainingBlock = newFrame;
3749 nsIFrame* possiblyLeafFrame = newFrame;
3750 nsContainerFrame* outerFrame = nullptr;
3751 if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000) {
3752 RefPtr<ComputedStyle> outerStyle =
3753 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3754 data->mAnonBoxPseudo, computedStyle);
3755#ifdef DEBUG1
3756 nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
3757 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"
, 3757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containerFrame"
")"); do { *((volatile int*)__null) = 3757; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3758#endif
3759 nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
3760 nsContainerFrame* innerFrame;
3761 if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) {
3762 switch (display->DisplayInside()) {
3763 case StyleDisplayInside::Flex:
3764 outerFrame = NS_NewFlexContainerFrame(mPresShell, outerStyle);
3765 InitAndRestoreFrame(aState, content, container, outerFrame);
3766 innerFrame = outerFrame;
3767 break;
3768 case StyleDisplayInside::Grid:
3769 outerFrame = NS_NewGridContainerFrame(mPresShell, outerStyle);
3770 InitAndRestoreFrame(aState, content, container, outerFrame);
3771 innerFrame = outerFrame;
3772 break;
3773 default: {
3774 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3775 if (outerStyle->StyleColumn()->IsColumnContainerStyle()) {
3776 outerFrame = BeginBuildingColumns(aState, content, container,
3777 innerFrame, outerStyle);
3778 } else {
3779 // No need to create column container. Initialize innerFrame.
3780 InitAndRestoreFrame(aState, content, container, innerFrame);
3781 outerFrame = innerFrame;
3782 }
3783 break;
3784 }
3785 }
3786 } else {
3787 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3788 InitAndRestoreFrame(aState, content, container, innerFrame);
3789 outerFrame = innerFrame;
3790 }
3791
3792 SetInitialSingleChild(container, outerFrame);
3793
3794 container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3795
3796 // Now figure out whether newFrame or outerFrame should be the
3797 // absolute container.
3798 if (outerFrame->IsAbsPosContainingBlock()) {
3799 maybeAbsoluteContainingBlock = outerFrame;
3800 maybeAbsoluteContainingBlockStyleFrame = outerFrame;
3801 innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3802 }
3803
3804 // Our kids should go into the innerFrame.
3805 newFrame = innerFrame;
3806 }
3807
3808 aState.AddChild(primaryFrame, aFrameList, content, aParentFrame,
3809 allowOutOfFlow, allowOutOfFlow);
3810
3811 nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
3812 if (newFrameAsContainer) {
3813 // Process the child content if requested
3814 nsFrameList childList;
3815 nsFrameConstructorSaveState absoluteSaveState;
3816
3817 if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10) {
3818 aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
3819 } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH0x200)) {
3820 maybeAbsoluteContainingBlock->AddStateBits(
3821 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3822 if (maybeAbsoluteContainingBlockStyleFrame->IsAbsPosContainingBlock()) {
3823 auto* cf =
3824 static_cast<nsContainerFrame*>(maybeAbsoluteContainingBlock);
3825 aState.PushAbsoluteContainingBlock(
3826 cf, maybeAbsoluteContainingBlockStyleFrame, absoluteSaveState);
3827 }
3828 }
3829
3830 nsFrameConstructorSaveState floatSaveState;
3831 aState.MaybePushFloatContainingBlock(newFrameAsContainer, floatSaveState);
3832
3833 if (bits & FCDATA_USE_CHILD_ITEMS0x10000) {
3834 // At this point, we have not set up the auto value for this frame, and
3835 // no caller will have set it so it is not redundant and therefor will
3836 // not assert.
3837 AutoFrameConstructionPageName pageNameTracker(aState,
3838 newFrameAsContainer);
3839 ConstructFramesFromItemList(
3840 aState, aItem.mChildItems, newFrameAsContainer,
3841 bits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
3842 } else {
3843 // Process the child frames.
3844 ProcessChildren(aState, content, computedStyle, newFrameAsContainer,
3845 !(bits & FCDATA_DISALLOW_GENERATED_CONTENT0x400), childList,
3846 (bits & FCDATA_ALLOW_BLOCK_STYLES0x8000) != 0,
3847 possiblyLeafFrame);
3848 }
3849
3850 if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS0x20) {
3851 nsFrameList newList;
3852 nsFrameList currentBlockList;
3853 nsIFrame* f;
3854 while ((f = childList.FirstChild()) != nullptr) {
3855 bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
3856 if (!wrapFrame) {
3857 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3858 currentBlockList, newList);
3859 }
3860
3861 childList.RemoveFrame(f);
3862 if (wrapFrame) {
3863 currentBlockList.AppendFrame(nullptr, f);
3864 } else {
3865 newList.AppendFrame(nullptr, f);
3866 }
3867 }
3868 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3869 currentBlockList, newList);
3870
3871 if (childList.NotEmpty()) {
3872 // an error must have occurred, delete unprocessed frames
3873 DestroyFramesInList(mPresShell, childList);
3874 }
3875
3876 childList = std::move(newList);
3877 }
3878
3879 if (!(bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) ||
3880 !MayNeedToCreateColumnSpanSiblings(newFrameAsContainer, childList)) {
3881 // Set the frame's initial child list. Note that MathML depends on this
3882 // being called even if childList is empty!
3883 newFrameAsContainer->SetInitialChildList(FrameChildListID::Principal,
3884 std::move(childList));
3885 } else {
3886 // Extract any initial non-column-span kids, and put them in inner
3887 // frame's child list.
3888 nsFrameList initialNonColumnSpanKids =
3889 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3890 newFrameAsContainer->SetInitialChildList(
3891 FrameChildListID::Principal, std::move(initialNonColumnSpanKids));
3892
3893 if (childList.NotEmpty()) {
3894 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3895 aState, newFrameAsContainer, childList,
3896 // Column content should never be a absolute/fixed positioned
3897 // containing block. Pass nullptr as aPositionedFrame.
3898 nullptr);
3899
3900 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"
, 3902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3902; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3901 "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"
, 3902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3902; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3902 "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"
, 3902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3902; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
3903 FinishBuildingColumns(aState, outerFrame, newFrameAsContainer,
3904 columnSpanSiblings);
3905 }
3906 }
3907 }
3908 }
3909
3910 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"
, 3912); MOZ_PretendNoReturn(); } } while (0)
3911 ((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"
, 3912); MOZ_PretendNoReturn(); } } while (0)
3912 "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"
, 3912); MOZ_PretendNoReturn(); } } while (0)
;
3913
3914 // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
3915 // generated content that doesn't have one yet. Note that we have to examine
3916 // the frame bit, because by this point mIsGeneratedContent has been cleared
3917 // on aItem.
3918 if ((!aState.mCreatingExtraFrames ||
3919 (aItem.mContent->IsRootOfNativeAnonymousSubtree() &&
3920 !aItem.mContent->GetPrimaryFrame())) &&
3921 !(bits & FCDATA_SKIP_FRAMESET0x1)) {
3922 aItem.mContent->SetPrimaryFrame(primaryFrame);
3923 ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
3924 }
3925}
3926
3927static void GatherSubtreeElements(Element* aElement,
3928 nsTArray<Element*>& aElements) {
3929 aElements.AppendElement(aElement);
3930 StyleChildrenIterator iter(aElement);
3931 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
3932 if (!c->IsElement()) {
3933 continue;
3934 }
3935 GatherSubtreeElements(c->AsElement(), aElements);
3936 }
3937}
3938
3939nsresult nsCSSFrameConstructor::GetAnonymousContent(
3940 nsIContent* aParent, nsIFrame* aParentFrame,
3941 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent) {
3942 nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
3943 if (!creator) {
3944 return NS_OK;
3945 }
3946
3947 nsresult rv = creator->CreateAnonymousContent(aContent);
3948 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3949 // CreateAnonymousContent failed, e.g. because the page has a <use> loop.
3950 return rv;
3951 }
3952
3953 if (aContent.IsEmpty()) {
3954 return NS_OK;
3955 }
3956
3957 const bool devtoolsEventsEnabled =
3958 mDocument->DevToolsAnonymousAndShadowEventsEnabled();
3959
3960 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"
, 3960); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsElement()"
")"); do { *((volatile int*)__null) = 3960; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3961 for (const auto& info : aContent) {
3962 // get our child's content and set its parent to our content
3963 nsIContent* content = info.mContent;
3964 content->SetIsNativeAnonymousRoot();
3965
3966 BindContext context(*aParent->AsElement(), BindContext::ForNativeAnonymous);
3967 rv = content->BindToTree(context, *aParent);
3968
3969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3970 content->UnbindFromTree();
3971 return rv;
3972 }
3973
3974 if (devtoolsEventsEnabled) {
3975 content->QueueDevtoolsAnonymousEvent(/* aIsRemove = */ false);
3976 }
3977 }
3978
3979 // Some situations where we don't cache anonymous content styles:
3980 //
3981 // * when visibility or pointer-events is anything other than the initial
3982 // value; we rely on visibility and pointer-events inheriting into anonymous
3983 // content, but don't bother adding this state to the AnonymousContentKey,
3984 // since it's not so common. Note that with overlay scrollbars, scrollbars
3985 // always start off with pointer-events: none so we don't need to check for
3986 // that in that case.
3987 //
3988 // * when the medium is anything other than screen; some UA style sheet rules
3989 // apply in e.g. print medium, and will give different results from the
3990 // cached styles
3991 Maybe<bool> computedAllowStyleCaching;
3992 auto ComputeAllowStyleCaching = [&] {
3993 if (!StaticPrefs::layout_css_cached_scrollbar_styles_enabled()) {
3994 return false;
3995 }
3996 if (aParentFrame->StyleVisibility()->mVisible != StyleVisibility::Visible) {
3997 return false;
3998 }
3999 nsPresContext* pc = mPresShell->GetPresContext();
4000 if (!pc->UseOverlayScrollbars() &&
4001 aParentFrame->StyleUI()->ComputedPointerEvents() !=
4002 StylePointerEvents::Auto) {
4003 return false;
4004 }
4005 if (pc->Medium() != nsGkAtoms::screen) {
4006 return false;
4007 }
4008 return true;
4009 };
4010
4011 auto AllowStyleCaching = [&] {
4012 if (computedAllowStyleCaching.isNothing()) {
4013 computedAllowStyleCaching.emplace(ComputeAllowStyleCaching());
4014 }
4015 return computedAllowStyleCaching.value();
4016 };
4017
4018 // Compute styles for the anonymous content tree.
4019 ServoStyleSet* styleSet = mPresShell->StyleSet();
4020 for (auto& info : aContent) {
4021 Element* e = Element::FromNode(info.mContent);
4022 if (!e) {
4023 continue;
4024 }
4025
4026 if (info.mKey == AnonymousContentKey::None || !AllowStyleCaching()) {
4027 // Most NAC subtrees do not use caching of computed styles. Just go
4028 // ahead and eagerly style the subtree.
4029 styleSet->StyleNewSubtree(e);
4030 continue;
4031 }
4032
4033 // We have a NAC subtree for which we can use cached styles.
4034 AutoTArray<RefPtr<ComputedStyle>, 2> cachedStyles;
4035 AutoTArray<Element*, 2> elements;
4036
4037 GatherSubtreeElements(e, elements);
4038 styleSet->GetCachedAnonymousContentStyles(info.mKey, cachedStyles);
4039
4040 if (cachedStyles.IsEmpty()) {
4041 // We haven't stored cached styles for this kind of NAC subtree yet.
4042 // Eagerly compute those styles, then cache them for later.
4043 styleSet->StyleNewSubtree(e);
4044 for (Element* e : elements) {
4045 if (e->HasServoData()) {
4046 cachedStyles.AppendElement(ServoStyleSet::ResolveServoStyle(*e));
4047 } else {
4048 cachedStyles.AppendElement(nullptr);
4049 }
4050 }
4051 styleSet->PutCachedAnonymousContentStyles(info.mKey,
4052 std::move(cachedStyles));
4053 continue;
4054 }
4055
4056 // We previously stored cached styles for this kind of NAC subtree.
4057 // Iterate over them and set them on the subtree's elements.
4058 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"
, 4059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4059; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4059 "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"
, 4059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4059; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4060 for (size_t i = 0, len = cachedStyles.Length(); i != len; ++i) {
4061 if (cachedStyles[i]) {
4062#ifdef DEBUG1
4063 // Assert that our cached style is the same as one we could compute.
4064 RefPtr<ComputedStyle> cs = styleSet->ResolveStyleLazily(*elements[i]);
4065 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4068; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4066 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4068; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4067 "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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4068; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4068 "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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4068; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4069 // All overlay scrollbars start off as inactive, so we can rely on their
4070 // pointer-events value being always none.
4071 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"
, 4073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4072 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"
, 4073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4073 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"
, 4073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4074#endif
4075 Servo_SetExplicitStyle(elements[i], cachedStyles[i]);
4076 }
4077 }
4078 }
4079
4080 return NS_OK;
4081}
4082
4083// XUL frames are not allowed to be out of flow.
4084#define SIMPLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200) \
4085 FrameConstructionData(_func, \
4086 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_SKIP_ABSPOS_PUSH0x200)
4087#define SCROLLABLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200 | 0x80) \
4088 FrameConstructionData(_func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4089 FCDATA_SKIP_ABSPOS_PUSH0x200 | \
4090 FCDATA_MAY_NEED_SCROLLFRAME0x80)
4091// .. but we allow some XUL frames to be _containers_ for out-of-flow content
4092// (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
4093#define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)FrameConstructionData( _func, 0x8 | 0x80) \
4094 FrameConstructionData( \
4095 _func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_MAY_NEED_SCROLLFRAME0x80)
4096
4097#define SIMPLE_XUL_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func, 0x8 | 0x200)} \
4098 {nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200)}
4099#define SCROLLABLE_XUL_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func, 0x8 | 0x200 | 0x80
)}
\
4100 {nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200 | 0x80)}
4101
4102/* static */
4103const nsCSSFrameConstructor::FrameConstructionData*
4104nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
4105 ComputedStyle& aStyle) {
4106 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"
, 4106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsXULElement()"
")"); do { *((volatile int*)__null) = 4106; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4107 static constexpr FrameConstructionData kPopupData(
4108 NS_NewMenuPopupFrame, FCDATA_IS_POPUP0x100 | FCDATA_SKIP_ABSPOS_PUSH0x200);
4109
4110 static constexpr FrameConstructionDataByTag sXULTagData[] = {
4111 SIMPLE_XUL_CREATE(image, NS_NewXULImageFrame){nsGkAtoms::image, FrameConstructionData(NS_NewXULImageFrame,
0x8 | 0x200)}
,
4112 SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame){nsGkAtoms::treechildren, FrameConstructionData(NS_NewTreeBodyFrame
, 0x8 | 0x200)}
,
4113 SIMPLE_TAG_CHAIN(label,{nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4114 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4115 SIMPLE_TAG_CHAIN(description,{nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4116 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4117#ifdef XP_MACOSX
4118 SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData){nsGkAtoms::menubar, FrameConstructionData(nsCSSFrameConstructor
::FindXULMenubarData)}
,
4119#endif /* XP_MACOSX */
4120 SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4121 SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame){nsGkAtoms::editor, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4122 SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame){nsGkAtoms::browser, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4123 SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame){nsGkAtoms::splitter, FrameConstructionData(NS_NewSplitterFrame
, 0x8 | 0x200)}
,
4124 SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame){nsGkAtoms::scrollbar, FrameConstructionData(NS_NewScrollbarFrame
, 0x8 | 0x200)}
,
4125 SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame){nsGkAtoms::slider, FrameConstructionData(NS_NewSliderFrame, 0x8
| 0x200)}
,
4126 SIMPLE_XUL_CREATE(thumb, NS_NewSimpleXULLeafFrame){nsGkAtoms::thumb, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4127 SIMPLE_XUL_CREATE(scrollcorner, NS_NewSimpleXULLeafFrame){nsGkAtoms::scrollcorner, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4128 SIMPLE_XUL_CREATE(resizer, NS_NewSimpleXULLeafFrame){nsGkAtoms::resizer, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4129 SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame){nsGkAtoms::scrollbarbutton, FrameConstructionData(NS_NewScrollbarButtonFrame
, 0x8 | 0x200)}
,
4130 {nsGkAtoms::panel, kPopupData},
4131 {nsGkAtoms::menupopup, kPopupData},
4132 {nsGkAtoms::tooltip, kPopupData},
4133 };
4134
4135 return FindDataByTag(aElement, aStyle, sXULTagData, ArrayLength(sXULTagData));
4136}
4137
4138/* static */
4139const nsCSSFrameConstructor::FrameConstructionData*
4140nsCSSFrameConstructor::FindXULLabelOrDescriptionData(const Element& aElement,
4141 ComputedStyle&) {
4142 // Follow CSS display value if no value attribute
4143 if (!aElement.HasAttr(nsGkAtoms::value)) {
4144 return nullptr;
4145 }
4146
4147 // Follow CSS display if there's no crop="center".
4148 if (!aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::crop,
4149 nsGkAtoms::center, eCaseMatters)) {
4150 return nullptr;
4151 }
4152
4153 static constexpr FrameConstructionData sMiddleCroppingData =
4154 SIMPLE_XUL_FCDATA(NS_NewMiddleCroppingLabelFrame)FrameConstructionData(NS_NewMiddleCroppingLabelFrame, 0x8 | 0x200
)
;
4155 return &sMiddleCroppingData;
4156}
4157
4158#ifdef XP_MACOSX
4159/* static */
4160const nsCSSFrameConstructor::FrameConstructionData*
4161nsCSSFrameConstructor::FindXULMenubarData(const Element& aElement,
4162 ComputedStyle&) {
4163 if (aElement.OwnerDoc()->IsInChromeDocShell()) {
4164 BrowsingContext* bc = aElement.OwnerDoc()->GetBrowsingContext();
4165 bool isRoot = bc && !bc->GetParent();
4166 if (isRoot) {
4167 // This is the root. Suppress the menubar, since on Mac
4168 // window menus are not attached to the window.
4169 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4170 return &sSuppressData;
4171 }
4172 }
4173
4174 return nullptr;
4175}
4176#endif /* XP_MACOSX */
4177
4178already_AddRefed<ComputedStyle>
4179nsCSSFrameConstructor::BeginBuildingScrollContainerFrame(
4180 nsFrameConstructorState& aState, nsIContent* aContent,
4181 ComputedStyle* aContentStyle, nsContainerFrame* aParentFrame,
4182 PseudoStyleType aScrolledPseudo, bool aIsRoot,
4183 nsContainerFrame*& aNewFrame) {
4184 nsContainerFrame* scrollContainerFrame = aNewFrame;
4185
4186 if (!scrollContainerFrame) {
4187 scrollContainerFrame =
4188 NS_NewScrollContainerFrame(mPresShell, aContentStyle, aIsRoot);
4189 InitAndRestoreFrame(aState, aContent, aParentFrame, scrollContainerFrame);
4190 }
4191
4192 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"
, 4192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scrollContainerFrame"
")"); do { *((volatile int*)__null) = 4192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4193
4194 // if there are any anonymous children for the scroll frame, create
4195 // frames for them.
4196 //
4197 // We can't take the normal ProcessChildren path, because the NAC needs to
4198 // be parented to the scrollframe, and everything else needs to be parented
4199 // to the scrolledframe.
4200 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC;
4201 DebugOnly<nsresult> rv =
4202 GetAnonymousContent(aContent, scrollContainerFrame, scrollNAC);
4203 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"
, 4203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4203; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4204 nsFrameList anonymousList;
4205 if (!scrollNAC.IsEmpty()) {
4206 nsFrameConstructorSaveState floatSaveState;
4207 aState.MaybePushFloatContainingBlock(scrollContainerFrame, floatSaveState);
4208
4209 AutoFrameConstructionItemList items(this);
4210 AutoFrameConstructionPageName pageNameTracker(aState, scrollContainerFrame);
4211 AddFCItemsForAnonymousContent(aState, scrollContainerFrame, scrollNAC,
4212 items, pageNameTracker);
4213 ConstructFramesFromItemList(aState, items, scrollContainerFrame,
4214 /* aParentIsWrapperAnonBox = */ false,
4215 anonymousList);
4216 }
4217
4218 aNewFrame = scrollContainerFrame;
4219 scrollContainerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4220
4221 // we used the style that was passed in. So resolve another one.
4222 ServoStyleSet* styleSet = mPresShell->StyleSet();
4223 RefPtr<ComputedStyle> scrolledChildStyle =
4224 styleSet->ResolveInheritingAnonymousBoxStyle(aScrolledPseudo,
4225 aContentStyle);
4226
4227 scrollContainerFrame->SetInitialChildList(FrameChildListID::Principal,
4228 std::move(anonymousList));
4229
4230 return scrolledChildStyle.forget();
4231}
4232
4233void nsCSSFrameConstructor::FinishBuildingScrollContainerFrame(
4234 nsContainerFrame* aScrollContainerFrame, nsIFrame* aScrolledFrame) {
4235 aScrollContainerFrame->AppendFrames(
4236 FrameChildListID::Principal, nsFrameList(aScrolledFrame, aScrolledFrame));
4237}
4238
4239void nsCSSFrameConstructor::BuildScrollContainerFrame(
4240 nsFrameConstructorState& aState, nsIContent* aContent,
4241 ComputedStyle* aContentStyle, nsIFrame* aScrolledFrame,
4242 nsContainerFrame* aParentFrame, nsContainerFrame*& aNewFrame) {
4243 RefPtr<ComputedStyle> scrolledContentStyle =
4244 BeginBuildingScrollContainerFrame(
4245 aState, aContent, aContentStyle, aParentFrame,
4246 PseudoStyleType::scrolledContent, false, aNewFrame);
4247
4248 aScrolledFrame->SetComputedStyleWithoutNotification(scrolledContentStyle);
4249 InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
4250
4251 FinishBuildingScrollContainerFrame(aNewFrame, aScrolledFrame);
4252}
4253
4254const nsCSSFrameConstructor::FrameConstructionData*
4255nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
4256 const Element& aElement) {
4257 static_assert(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET28)),
4258 "Check eParentTypeCount should not overflow");
4259
4260 // The style system ensures that floated and positioned frames are
4261 // block-level.
4262 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"
, 4265); MOZ_PretendNoReturn(); } } while (0)
4263 !(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"
, 4265); MOZ_PretendNoReturn(); } } while (0)
4264 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"
, 4265); MOZ_PretendNoReturn(); } } while (0)
4265 "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"
, 4265); MOZ_PretendNoReturn(); } } while (0)
;
4266
4267 // If this is "body", try propagating its scroll style to the viewport
4268 // Note that we need to do this even if the body is NOT scrollable;
4269 // it might have dynamically changed from scrollable to not scrollable,
4270 // and that might need to be propagated.
4271 // XXXbz is this the right place to do this? If this code moves,
4272 // make this function static.
4273 bool propagatedScrollToViewport = false;
4274 if (aElement.IsHTMLElement(nsGkAtoms::body)) {
4275 if (nsPresContext* presContext = mPresShell->GetPresContext()) {
4276 propagatedScrollToViewport =
4277 presContext->UpdateViewportScrollStylesOverride() == &aElement;
4278 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"
, 4280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4279 !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"
, 4280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4280 "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"
, 4280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4280; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4281 }
4282 }
4283
4284 switch (aDisplay.DisplayInside()) {
4285 case StyleDisplayInside::Flow:
4286 case StyleDisplayInside::FlowRoot: {
4287 if (aDisplay.IsInlineFlow()) {
4288 static constexpr FrameConstructionData data(
4289 &nsCSSFrameConstructor::ConstructInline,
4290 FCDATA_IS_INLINE0x1000 | FCDATA_IS_LINE_PARTICIPANT0x2000);
4291 return &data;
4292 }
4293
4294 // If the frame is a block-level frame and is scrollable, then wrap it in
4295 // a scroll frame. Except we don't want to do that for paginated contexts
4296 // for frames that are block-outside and aren't frames for native
4297 // anonymous stuff.
4298 // XXX Ignore tables for the time being (except caption)
4299 const uint32_t kCaptionCtorFlags =
4300 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28);
4301 const bool caption = aDisplay.mDisplay == StyleDisplay::TableCaption;
4302 const bool needScrollFrame =
4303 aDisplay.IsScrollableOverflow() && !propagatedScrollToViewport;
4304 if (needScrollFrame) {
4305 const bool suppressScrollFrame =
4306 mPresShell->GetPresContext()->IsPaginated() &&
4307 aDisplay.IsBlockOutsideStyle() &&
4308 !aElement.IsInNativeAnonymousSubtree();
4309 if (!suppressScrollFrame) {
4310 static constexpr FrameConstructionData sScrollableBlockData[2] = {
4311 {&nsCSSFrameConstructor::ConstructScrollableBlock},
4312 {&nsCSSFrameConstructor::ConstructScrollableBlock,
4313 kCaptionCtorFlags}};
4314 return &sScrollableBlockData[caption];
4315 }
4316 }
4317
4318 // Handle various non-scrollable blocks.
4319 static constexpr FrameConstructionData sNonScrollableBlockData[2] = {
4320 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
4321 {&nsCSSFrameConstructor::ConstructNonScrollableBlock,
4322 kCaptionCtorFlags}};
4323 return &sNonScrollableBlockData[caption];
4324 }
4325 case StyleDisplayInside::Table: {
4326 static constexpr FrameConstructionData data(
4327 &nsCSSFrameConstructor::ConstructTable);
4328 return &data;
4329 }
4330 // NOTE: In the unlikely event that we add another table-part here that
4331 // has a desired-parent-type (& hence triggers table fixup), we'll need to
4332 // also update the flexbox chunk in ComputedStyle::ApplyStyleFixups().
4333 case StyleDisplayInside::TableRowGroup: {
4334 static constexpr FrameConstructionData data(
4335 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4336 FCDATA_IS_TABLE_PART0x800 |
4337 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4338 return &data;
4339 }
4340 case StyleDisplayInside::TableColumn: {
4341 static constexpr FrameConstructionData data(
4342 &nsCSSFrameConstructor::ConstructTableCol,
4343 FCDATA_IS_TABLE_PART0x800 |
4344 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup)(((uint32_t)(eTypeColGroup)) << 28));
4345 return &data;
4346 }
4347 case StyleDisplayInside::TableColumnGroup: {
4348 static constexpr FrameConstructionData data(
4349 ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
4350 FCDATA_IS_TABLE_PART0x800 | FCDATA_DISALLOW_OUT_OF_FLOW0x8 |
4351 FCDATA_SKIP_ABSPOS_PUSH0x200 |
4352 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4353 return &data;
4354 }
4355 case StyleDisplayInside::TableHeaderGroup: {
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::TableFooterGroup: {
4363 static constexpr FrameConstructionData data(
4364 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4365 FCDATA_IS_TABLE_PART0x800 |
4366 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4367 return &data;
4368 }
4369 case StyleDisplayInside::TableRow: {
4370 static constexpr FrameConstructionData data(
4371 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4372 FCDATA_IS_TABLE_PART0x800 |
4373 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28));
4374 return &data;
4375 }
4376 case StyleDisplayInside::TableCell: {
4377 static constexpr FrameConstructionData data(
4378 &nsCSSFrameConstructor::ConstructTableCell,
4379 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28));
4380 return &data;
4381 }
4382 case StyleDisplayInside::Flex:
4383 case StyleDisplayInside::WebkitBox: {
4384 static constexpr FrameConstructionData nonScrollableData(
4385 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
);
4386 static constexpr FrameConstructionData data(
4387 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
,
4388 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4389 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4390 : &data;
4391 }
4392 case StyleDisplayInside::Grid: {
4393 static constexpr FrameConstructionData nonScrollableData(
4394 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
);
4395 static constexpr FrameConstructionData data(
4396 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
,
4397 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4398 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4399 : &data;
4400 }
4401 case StyleDisplayInside::Ruby: {
4402 static constexpr FrameConstructionData data[] = {
4403 {&nsCSSFrameConstructor::ConstructBlockRubyFrame,
4404 FCDATA_MAY_NEED_SCROLLFRAME0x80},
4405 {ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
, FCDATA_IS_LINE_PARTICIPANT0x2000}};
4406 bool isInline = aDisplay.DisplayOutside() == StyleDisplayOutside::Inline;
4407 return &data[isInline];
4408 }
4409 case StyleDisplayInside::RubyBase: {
4410 static constexpr FrameConstructionData data(
4411 ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
4412 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4413 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28));
4414 return &data;
4415 }
4416 case StyleDisplayInside::RubyBaseContainer: {
4417 static constexpr FrameConstructionData data(
4418 ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
4419 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4420 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4421 return &data;
4422 }
4423 case StyleDisplayInside::RubyText: {
4424 static constexpr FrameConstructionData data(
4425 ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
4426 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4427 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28));
4428 return &data;
4429 }
4430 case StyleDisplayInside::RubyTextContainer: {
4431 static constexpr FrameConstructionData data(
4432 ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
4433 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4434 return &data;
4435 }
4436 default:
4437 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"
, 4437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unknown 'display' value" ")"); do
{ *((volatile int*)__null) = 4437; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4438 return nullptr;
4439 }
4440}
4441
4442nsIFrame* nsCSSFrameConstructor::ConstructScrollableBlock(
4443 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4444 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4445 nsFrameList& aFrameList) {
4446 nsIContent* const content = aItem.mContent;
4447 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4448
4449 nsContainerFrame* newFrame = nullptr;
4450 RefPtr<ComputedStyle> scrolledContentStyle =
4451 BeginBuildingScrollContainerFrame(
4452 aState, content, computedStyle,
4453 aState.GetGeometricParent(*aDisplay, aParentFrame),
4454 PseudoStyleType::scrolledContent, false, newFrame);
4455
4456 // Create our block frame
4457 // pass a temporary stylecontext, the correct one will be set later
4458 nsContainerFrame* scrolledFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4459
4460 // Make sure to AddChild before we call ConstructBlock so that we
4461 // end up before our descendants in fixed-pos lists as needed.
4462 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
4463
4464 nsFrameList blockList;
4465 ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
4466 &scrolledFrame, blockList,
4467 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4468
4469 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"
, 4470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4470; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4470 "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"
, 4470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4470; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4471 FinishBuildingScrollContainerFrame(newFrame, scrolledFrame);
4472
4473 return newFrame;
4474}
4475
4476nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlock(
4477 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4478 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4479 nsFrameList& aFrameList) {
4480 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4481 nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4482 ConstructBlock(aState, aItem.mContent,
4483 aState.GetGeometricParent(*aDisplay, aParentFrame),
4484 aParentFrame, computedStyle, &newFrame, aFrameList,
4485 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4486 return newFrame;
4487}
4488
4489void nsCSSFrameConstructor::InitAndRestoreFrame(
4490 const nsFrameConstructorState& aState, nsIContent* aContent,
4491 nsContainerFrame* aParentFrame, nsIFrame* aNewFrame, bool aAllowCounters) {
4492 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"
, 4492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame" ") ("
"Null frame cannot be initialized" ")"); do { *((volatile int
*)__null) = 4492; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4493
4494 // Initialize the frame
4495 aNewFrame->Init(aContent, aParentFrame, nullptr);
4496 aNewFrame->AddStateBits(aState.mAdditionalStateBits);
4497
4498 if (aState.mFrameState) {
4499 // Restore frame state for just the newly created frame.
4500 RestoreFrameStateFor(aNewFrame, aState.mFrameState);
4501 }
4502
4503 if (aAllowCounters &&
4504 mContainStyleScopeManager.AddCounterChanges(aNewFrame)) {
4505 CountersDirty();
4506 }
4507}
4508
4509already_AddRefed<ComputedStyle> nsCSSFrameConstructor::ResolveComputedStyle(
4510 nsIContent* aContent) {
4511 if (auto* element = Element::FromNode(aContent)) {
4512 return ServoStyleSet::ResolveServoStyle(*element);
4513 }
4514
4515 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"
, 4517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4516 "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"
, 4517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4517 "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"
, 4517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4518
4519 Element* parent = aContent->GetFlattenedTreeParentElement();
4520 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"
, 4520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"Text out of the flattened tree?" ")"); do { *((volatile int
*)__null) = 4520; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4521
4522 // FIXME(emilio): The const_cast is unfortunate, but it's not worse than what
4523 // we did before.
4524 //
4525 // We could use ResolveServoStyle, but that would involve extra unnecessary
4526 // refcount traffic...
4527 auto* parentStyle =
4528 const_cast<ComputedStyle*>(Servo_Element_GetMaybeOutOfDateStyle(parent));
4529 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"
, 4530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4530; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4530 "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"
, 4530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4530; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4531 return mPresShell->StyleSet()->ResolveStyleForText(aContent, parentStyle);
4532}
4533
4534// MathML Mod - RBS
4535void nsCSSFrameConstructor::FlushAccumulatedBlock(
4536 nsFrameConstructorState& aState, nsIContent* aContent,
4537 nsContainerFrame* aParentFrame, nsFrameList& aBlockList,
4538 nsFrameList& aNewList) {
4539 if (aBlockList.IsEmpty()) {
4540 // Nothing to do
4541 return;
4542 }
4543
4544 auto anonPseudo = PseudoStyleType::mozMathMLAnonymousBlock;
4545
4546 ComputedStyle* parentContext =
4547 nsIFrame::CorrectStyleParentFrame(aParentFrame, anonPseudo)->Style();
4548 ServoStyleSet* styleSet = mPresShell->StyleSet();
4549 RefPtr<ComputedStyle> blockContext =
4550 styleSet->ResolveInheritingAnonymousBoxStyle(anonPseudo, parentContext);
4551
4552 // then, create a block frame that will wrap the child frames. Make it a
4553 // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
4554 // is not a suitable block.
4555 nsContainerFrame* blockFrame =
4556 NS_NewMathMLmathBlockFrame(mPresShell, blockContext);
4557
4558 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
4559 ReparentFrames(this, blockFrame, aBlockList, false);
4560 // We have to walk over aBlockList before we hand it over to blockFrame.
4561 for (nsIFrame* f : aBlockList) {
4562 f->SetParentIsWrapperAnonBox();
4563 }
4564 // abs-pos and floats are disabled in MathML children so we don't have to
4565 // worry about messing up those.
4566 blockFrame->SetInitialChildList(FrameChildListID::Principal,
4567 std::move(aBlockList));
4568 aNewList.AppendFrame(nullptr, blockFrame);
4569}
4570
4571// Only <math> elements can be floated or positioned. All other MathML
4572// should be in-flow.
4573#define SIMPLE_MATHML_CREATE(_tag, _func){ nsGkAtoms::_tag, { _func, 0x8 | 0x10 | 0x20 } } \
4574 { \
4575 nsGkAtoms::_tag, { \
4576 _func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4577 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | \
4578 FCDATA_WRAP_KIDS_IN_BLOCKS0x20 \
4579 } \
4580 }
4581
4582/* static */
4583const nsCSSFrameConstructor::FrameConstructionData*
4584nsCSSFrameConstructor::FindMathMLData(const Element& aElement,
4585 ComputedStyle& aStyle) {
4586 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"
, 4586); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsMathMLElement()"
")"); do { *((volatile int*)__null) = 4586; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4587
4588 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4589
4590 // Handle <math> specially, because it sometimes produces inlines
4591 if (tag == nsGkAtoms::math) {
4592 // The IsBlockOutsideStyle() check must match what
4593 // specified::Display::equivalent_block_display is checking for
4594 // already-block-outside things. Though the behavior here for the
4595 // display:table case is pretty weird...
4596 if (aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
4597 static constexpr FrameConstructionData sBlockMathData(
4598 ToCreationFunc(NS_NewMathMLmathBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathBlockFrame(aPs, aStyle); }
,
4599 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4600 return &sBlockMathData;
4601 }
4602
4603 static constexpr FrameConstructionData sInlineMathData(
4604 ToCreationFunc(NS_NewMathMLmathInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathInlineFrame(aPs, aStyle); }
,
4605 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4606 FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4607 return &sInlineMathData;
4608 }
4609
4610 static constexpr FrameConstructionDataByTag sMathMLData[] = {
4611 SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame){ nsGkAtoms::annotation_, { NS_NewMathMLTokenFrame, 0x8 | 0x10
| 0x20 } }
,
4612 SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame){ nsGkAtoms::annotation_xml_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4613 SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame){ nsGkAtoms::mi_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4614 SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame){ nsGkAtoms::mn_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4615 SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame){ nsGkAtoms::ms_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4616 SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame){ nsGkAtoms::mtext_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4617 SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame){ nsGkAtoms::mo_, { NS_NewMathMLmoFrame, 0x8 | 0x10 | 0x20 } },
4618 SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame){ nsGkAtoms::mfrac_, { NS_NewMathMLmfracFrame, 0x8 | 0x10 | 0x20
} }
,
4619 SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4620 SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msub_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4621 SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msubsup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 |
0x10 | 0x20 } }
,
4622 SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munder_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4623 SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::mover_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4624 SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munderover_, { NS_NewMathMLmunderoverFrame, 0x8 |
0x10 | 0x20 } }
,
4625 SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmrowFrame){ nsGkAtoms::mphantom_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
,
4626 SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame){ nsGkAtoms::mpadded_, { NS_NewMathMLmpaddedFrame, 0x8 | 0x10
| 0x20 } }
,
4627 SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame){ nsGkAtoms::mspace_, { NS_NewMathMLmspaceFrame, 0x8 | 0x10 |
0x20 } }
,
4628 SIMPLE_MATHML_CREATE(none, NS_NewMathMLmrowFrame){ nsGkAtoms::none, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4629 SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmrowFrame){ nsGkAtoms::mprescripts_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4630 SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmrowFrame){ nsGkAtoms::mfenced_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4631 SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::mmultiscripts_, { NS_NewMathMLmmultiscriptsFrame
, 0x8 | 0x10 | 0x20 } }
,
4632 SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame){ nsGkAtoms::mstyle_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4633 SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmrootFrame){ nsGkAtoms::msqrt_, { NS_NewMathMLmrootFrame, 0x8 | 0x10 | 0x20
} }
,
4634 SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame){ nsGkAtoms::mroot_, { NS_NewMathMLmrootFrame, 0x8 | 0x10 | 0x20
} }
,
4635 SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmrowFrame){ nsGkAtoms::maction_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4636 SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame){ nsGkAtoms::mrow_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4637 SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame){ nsGkAtoms::merror_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4638 SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame){ nsGkAtoms::menclose_, { NS_NewMathMLmencloseFrame, 0x8 | 0x10
| 0x20 } }
,
4639 SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLmrowFrame){ nsGkAtoms::semantics_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
};
4640
4641 return FindDataByTag(aElement, aStyle, sMathMLData, ArrayLength(sMathMLData));
4642}
4643
4644nsContainerFrame* nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
4645 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4646 nsContainerFrame* aParentFrame, nsFrameList& aFrameList,
4647 ContainerFrameCreationFunc aConstructor,
4648 ContainerFrameCreationFunc aInnerConstructor, PseudoStyleType aInnerPseudo,
4649 bool aCandidateRootFrame) {
4650 nsIContent* const content = aItem.mContent;
4651 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4652
4653 // Create the outer frame:
4654 nsContainerFrame* newFrame = aConstructor(mPresShell, computedStyle);
4655
4656 InitAndRestoreFrame(aState, content,
4657 aCandidateRootFrame
4658 ? aState.GetGeometricParent(
4659 *computedStyle->StyleDisplay(), aParentFrame)
4660 : aParentFrame,
4661 newFrame);
4662 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4663
4664 // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
4665 RefPtr<ComputedStyle> scForAnon =
4666 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(aInnerPseudo,
4667 computedStyle);
4668
4669 // Create the anonymous inner wrapper frame
4670 nsContainerFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
4671
4672 InitAndRestoreFrame(aState, content, newFrame, innerFrame);
4673
4674 // Put the newly created frames into the right child list
4675 SetInitialSingleChild(newFrame, innerFrame);
4676
4677 aState.AddChild(newFrame, aFrameList, content, aParentFrame,
4678 aCandidateRootFrame, aCandidateRootFrame);
4679
4680 if (!mRootElementFrame && aCandidateRootFrame) {
4681 mRootElementFrame = newFrame;
4682 }
4683
4684 nsFrameConstructorSaveState floatSaveState;
4685 aState.MaybePushFloatContainingBlock(innerFrame, floatSaveState);
4686
4687 nsFrameList childList;
4688
4689 // Process children
4690 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
4691 ConstructFramesFromItemList(
4692 aState, aItem.mChildItems, innerFrame,
4693 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
4694 } else {
4695 ProcessChildren(aState, content, computedStyle, innerFrame, true, childList,
4696 false);
4697 }
4698
4699 // Set the inner wrapper frame's initial primary list
4700 innerFrame->SetInitialChildList(FrameChildListID::Principal,
4701 std::move(childList));
4702
4703 return newFrame;
4704}
4705
4706nsIFrame* nsCSSFrameConstructor::ConstructOuterSVG(
4707 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4708 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4709 nsFrameList& aFrameList) {
4710 return ConstructFrameWithAnonymousChild(
4711 aState, aItem, aParentFrame, aFrameList, NS_NewSVGOuterSVGFrame,
4712 NS_NewSVGOuterSVGAnonChildFrame, PseudoStyleType::mozSVGOuterSVGAnonChild,
4713 true);
4714}
4715
4716nsIFrame* nsCSSFrameConstructor::ConstructMarker(
4717 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4718 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4719 nsFrameList& aFrameList) {
4720 return ConstructFrameWithAnonymousChild(
4721 aState, aItem, aParentFrame, aFrameList, NS_NewSVGMarkerFrame,
4722 NS_NewSVGMarkerAnonChildFrame, PseudoStyleType::mozSVGMarkerAnonChild,
4723 false);
4724}
4725
4726// Only outer <svg> elements can be floated or positioned. All other SVG
4727// should be in-flow.
4728#define SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
\
4729 FrameConstructionData(ToCreationFunc(_func)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
_func(aPs, aStyle); }
, \
4730 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4731 FCDATA_SKIP_ABSPOS_PUSH0x200 | \
4732 FCDATA_DISALLOW_GENERATED_CONTENT0x400)
4733#define SIMPLE_SVG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8
| 0x200 | 0x400)}
\
4734 {nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
}
4735
4736/* static */
4737const nsCSSFrameConstructor::FrameConstructionData*
4738nsCSSFrameConstructor::FindSVGData(const Element& aElement,
4739 nsIFrame* aParentFrame,
4740 bool aIsWithinSVGText,
4741 bool aAllowsTextPathChild,
4742 ComputedStyle& aStyle) {
4743 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"
, 4743); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsSVGElement()"
")"); do { *((volatile int*)__null) = 4743; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4744
4745 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4746 static constexpr FrameConstructionData sContainerData =
4747 SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)
;
4748
4749 bool parentIsSVG = aIsWithinSVGText;
4750 nsIContent* parentContent =
4751 aParentFrame ? aParentFrame->GetContent() : nullptr;
4752
4753 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4754
4755 // XXXbz should this really be based on the tag of the parent frame's content?
4756 // Should it not be based on the type of the parent frame (e.g. whether it's
4757 // an SVG frame)?
4758 if (parentContent) {
4759 // It's not clear whether the SVG spec intends to allow any SVG
4760 // content within svg:foreignObject at all (SVG 1.1, section
4761 // 23.2), but if it does, it better be svg:svg. So given that
4762 // we're allowing it, treat it as a non-SVG parent.
4763 parentIsSVG =
4764 parentContent->IsSVGElement() &&
4765 parentContent->NodeInfo()->NameAtom() != nsGkAtoms::foreignObject;
4766 }
4767
4768 if ((tag != nsGkAtoms::svg && !parentIsSVG) ||
4769 (tag == nsGkAtoms::desc || tag == nsGkAtoms::title ||
4770 tag == nsGkAtoms::metadata)) {
4771 // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
4772 // svg:svg not contained within svg:svg are incorrect, although they
4773 // don't seem to specify error handling. Ignore them, since many of
4774 // our frame classes can't deal. It *may* be that the document
4775 // should at that point be considered in error according to F.2, but
4776 // it's hard to tell.
4777 //
4778 // Style mutation can't change this situation, so don't bother
4779 // adding to the undisplayed content map.
4780 //
4781 // We don't currently handle any UI for desc/title/metadata
4782 return &sSuppressData;
4783 }
4784
4785 // We don't need frames for animation elements
4786 if (aElement.IsSVGAnimationElement()) {
4787 return &sSuppressData;
4788 }
4789
4790 if (tag == nsGkAtoms::svg && !parentIsSVG) {
4791 // We need outer <svg> elements to have an SVGOuterSVGFrame regardless
4792 // of whether they fail conditional processing attributes, since various
4793 // SVG frames assume that one exists. We handle the non-rendering
4794 // of failing outer <svg> element contents like <switch> statements,
4795 // and do the PassesConditionalProcessingTests call in
4796 // SVGOuterSVGFrame::Init.
4797 static constexpr FrameConstructionData sOuterSVGData(
4798 &nsCSSFrameConstructor::ConstructOuterSVG);
4799 return &sOuterSVGData;
4800 }
4801
4802 if (tag == nsGkAtoms::marker) {
4803 static constexpr FrameConstructionData sMarkerSVGData(
4804 &nsCSSFrameConstructor::ConstructMarker);
4805 return &sMarkerSVGData;
4806 }
4807
4808 if (!aElement.PassesConditionalProcessingTests()) {
4809 // Elements with failing conditional processing attributes never get
4810 // rendered. Note that this is not where we select which frame in a
4811 // <switch> to render! That happens in SVGSwitchFrame::PaintSVG.
4812 if (aIsWithinSVGText) {
4813 // SVGTextFrame doesn't handle conditional processing attributes,
4814 // so don't create frames for descendants of <text> with failing
4815 // attributes. We need frames not to be created so that text layout
4816 // is correct.
4817 return &sSuppressData;
4818 }
4819 // If we're not inside <text>, create an SVGContainerFrame (which is a
4820 // frame that doesn't render) so that paint servers can still be referenced,
4821 // even if they live inside an element with failing conditional processing
4822 // attributes.
4823 return &sContainerData;
4824 }
4825
4826 // Ensure that a stop frame is a child of a gradient and that gradients
4827 // can only have stop children.
4828 bool parentIsGradient = aParentFrame && static_cast<SVGGradientFrame*>(
4829 do_QueryFrame(aParentFrame));
4830 bool stop = (tag == nsGkAtoms::stop);
4831 if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
4832 return &sSuppressData;
4833 }
4834
4835 // Prevent bad frame types being children of filters or parents of filter
4836 // primitives. If aParentFrame is null, we know that the frame that will
4837 // be created will be an nsInlineFrame, so it can never be a filter.
4838 bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
4839 if ((parentIsFilter && !aElement.IsSVGFilterPrimitiveElement()) ||
4840 (!parentIsFilter && aElement.IsSVGFilterPrimitiveElement())) {
4841 return &sSuppressData;
4842 }
4843
4844 // Prevent bad frame types being children of filter primitives or parents of
4845 // filter primitive children. If aParentFrame is null, we know that the frame
4846 // that will be created will be an nsInlineFrame, so it can never be a filter
4847 // primitive.
4848 bool parentIsFEContainerFrame =
4849 aParentFrame && aParentFrame->IsSVGFEContainerFrame();
4850 if ((parentIsFEContainerFrame &&
4851 !aElement.IsSVGFilterPrimitiveChildElement()) ||
4852 (!parentIsFEContainerFrame &&
4853 aElement.IsSVGFilterPrimitiveChildElement())) {
4854 return &sSuppressData;
4855 }
4856
4857 // Special cases for text/tspan/textPath, because the kind of frame
4858 // they get depends on the parent frame. We ignore 'a' elements when
4859 // determining the parent, however.
4860 if (aIsWithinSVGText) {
4861 // If aIsWithinSVGText is true, then we know that the "SVG text uses
4862 // CSS frames" pref was true when this SVG fragment was first constructed.
4863 //
4864 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
4865 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
4866 // really know how to deal with it. This kinda sucks. :(
4867 if (aParentFrame && aParentFrame->GetContent() != aElement.GetParent()) {
4868 return &sSuppressData;
4869 }
4870
4871 // We don't use ConstructInline because we want different behavior
4872 // for generated content.
4873 static constexpr FrameConstructionData sTSpanData(
4874 ToCreationFunc(NS_NewInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewInlineFrame(aPs, aStyle); }
,
4875 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_SKIP_ABSPOS_PUSH0x200 |
4876 FCDATA_DISALLOW_GENERATED_CONTENT0x400 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4877 FCDATA_IS_INLINE0x1000 | FCDATA_USE_CHILD_ITEMS0x10000);
4878 if (tag == nsGkAtoms::textPath) {
4879 if (aAllowsTextPathChild) {
4880 return &sTSpanData;
4881 }
4882 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::a) {
4883 return &sTSpanData;
4884 }
4885 return &sSuppressData;
4886 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::textPath) {
4887 return &sSuppressData;
4888 }
4889
4890 static constexpr FrameConstructionDataByTag sSVGData[] = {
4891 SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame){nsGkAtoms::svg, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGInnerSVGFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4892 SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame){nsGkAtoms::g, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4893 SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame){nsGkAtoms::svgSwitch, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGSwitchFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4894 SIMPLE_SVG_CREATE(symbol, NS_NewSVGSymbolFrame){nsGkAtoms::symbol, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGSymbolFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4895 SIMPLE_SVG_CREATE(polygon, NS_NewSVGGeometryFrame){nsGkAtoms::polygon, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4896 SIMPLE_SVG_CREATE(polyline, NS_NewSVGGeometryFrame){nsGkAtoms::polyline, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4897 SIMPLE_SVG_CREATE(circle, NS_NewSVGGeometryFrame){nsGkAtoms::circle, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4898 SIMPLE_SVG_CREATE(ellipse, NS_NewSVGGeometryFrame){nsGkAtoms::ellipse, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4899 SIMPLE_SVG_CREATE(line, NS_NewSVGGeometryFrame){nsGkAtoms::line, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4900 SIMPLE_SVG_CREATE(rect, NS_NewSVGGeometryFrame){nsGkAtoms::rect, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4901 SIMPLE_SVG_CREATE(path, NS_NewSVGGeometryFrame){nsGkAtoms::path, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4902 SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame){nsGkAtoms::defs, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4903 {nsGkAtoms::text,
4904 {NS_NewSVGTextFrame,
4905 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_ALLOW_BLOCK_STYLES0x8000,
4906 PseudoStyleType::mozSVGText}},
4907 {nsGkAtoms::foreignObject,
4908 {ToCreationFunc(NS_NewSVGForeignObjectFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewSVGForeignObjectFrame(aPs, aStyle); }
,
4909 FCDATA_DISALLOW_OUT_OF_FLOW0x8, PseudoStyleType::mozSVGForeignContent}},
4910 SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame){nsGkAtoms::a, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGAFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4911 SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame){nsGkAtoms::linearGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGLinearGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4912 SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame){nsGkAtoms::radialGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGRadialGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4913 SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame){nsGkAtoms::stop, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGStopFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4914 SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame){nsGkAtoms::use, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGUseFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4915 SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame){nsGkAtoms::view, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGViewFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4916 SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame){nsGkAtoms::image, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGImageFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4917 SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame){nsGkAtoms::clipPath, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGClipPathFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4918 SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame){nsGkAtoms::filter, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFilterFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4919 SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame){nsGkAtoms::pattern, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGPatternFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4920 SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame){nsGkAtoms::mask, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGMaskFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4921 SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feDistantLight, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4922 SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::fePointLight, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4923 SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feSpotLight, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4924 SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame){nsGkAtoms::feBlend, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4925 SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feColorMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4926 SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncR, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4927 SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncG, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4928 SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncB, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4929 SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncA, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4930 SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame){nsGkAtoms::feComposite, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4931 SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame){nsGkAtoms::feComponentTransfer, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4932 SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feConvolveMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4933 SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feDiffuseLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4934 SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame){nsGkAtoms::feDisplacementMap, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4935 SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame){nsGkAtoms::feDropShadow, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4936 SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame){nsGkAtoms::feFlood, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4937 SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame){nsGkAtoms::feGaussianBlur, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4938 SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame){nsGkAtoms::feImage, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEImageFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4939 SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame){nsGkAtoms::feMerge, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4940 SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feMergeNode, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4941 SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame){nsGkAtoms::feMorphology, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4942 SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame){nsGkAtoms::feOffset, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4943 SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feSpecularLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4944 SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame){nsGkAtoms::feTile, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4945 SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame){nsGkAtoms::feTurbulence, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
};
4946
4947 const FrameConstructionData* data =
4948 FindDataByTag(aElement, aStyle, sSVGData, ArrayLength(sSVGData));
4949
4950 if (!data) {
4951 data = &sContainerData;
4952 }
4953
4954 return data;
4955}
4956
4957void nsCSSFrameConstructor::AppendPageBreakItem(
4958 nsIContent* aContent, FrameConstructionItemList& aItems) {
4959 RefPtr<ComputedStyle> pseudoStyle =
4960 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
4961 PseudoStyleType::pageBreak);
4962
4963 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"
, 4964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4964; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
4964 "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"
, 4964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4964; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4965
4966 static constexpr FrameConstructionData sPageBreakData(NS_NewPageBreakFrame,
4967 FCDATA_SKIP_FRAMESET0x1);
4968 aItems.AppendItem(this, &sPageBreakData, aContent, pseudoStyle.forget(),
4969 true);
4970}
4971
4972bool nsCSSFrameConstructor::ShouldCreateItemsForChild(
4973 nsFrameConstructorState& aState, nsIContent* aContent,
4974 nsContainerFrame* aParentFrame) {
4975 aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
4976 // XXX the GetContent() != aContent check is needed due to bug 135040.
4977 // Remove it once that's fixed.
4978 if (aContent->GetPrimaryFrame() &&
4979 aContent->GetPrimaryFrame()->GetContent() == aContent &&
4980 !aState.mCreatingExtraFrames) {
4981 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"
, 4983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4983; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4982 "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"
, 4983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4983; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4983 "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"
, 4983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4983; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4984 return false;
4985 }
4986
4987 // don't create a whitespace frame if aParent doesn't want it
4988 if (!NeedFrameFor(aState, aParentFrame, aContent)) {
4989 return false;
4990 }
4991
4992 // never create frames for comments or PIs
4993 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
4994 return false;
4995 }
4996
4997 return true;
4998}
4999
5000void nsCSSFrameConstructor::AddFrameConstructionItems(
5001 nsFrameConstructorState& aState, nsIContent* aContent,
5002 bool aSuppressWhiteSpaceOptimizations, const ComputedStyle& aParentStyle,
5003 const InsertionPoint& aInsertion, FrameConstructionItemList& aItems,
5004 ItemFlags aFlags) {
5005 nsContainerFrame* parentFrame = aInsertion.mParentFrame;
5006 if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) {
5007 return;
5008 }
5009 if (MOZ_UNLIKELY(aParentStyle.StyleContent()->mContent.IsNone())(__builtin_expect(!!(aParentStyle.StyleContent()->mContent
.IsNone()), 0))
&&
5010 StaticPrefs::layout_css_element_content_none_enabled()) {
5011 return;
5012 }
5013
5014 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5015 auto flags = aFlags + ItemFlag::AllowPageBreak;
5016 if (parentFrame) {
5017 if (parentFrame->IsInSVGTextSubtree()) {
5018 flags += ItemFlag::IsWithinSVGText;
5019 }
5020 if (parentFrame->IsBlockFrame() && parentFrame->GetParent() &&
5021 parentFrame->GetParent()->IsSVGTextFrame()) {
5022 flags += ItemFlag::AllowTextPathChild;
5023 }
5024 }
5025 AddFrameConstructionItemsInternal(aState, aContent, parentFrame,
5026 aSuppressWhiteSpaceOptimizations,
5027 computedStyle, flags, aItems);
5028}
5029
5030// Whether we should suppress frames for a child under a <select> frame.
5031//
5032// Never create frames for non-option/optgroup kids of <select> and non-option
5033// kids of <optgroup> inside a <select>.
5034static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
5035 const nsIContent& aChild) {
5036 if (!aParent ||
5037 !aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup,
5038 nsGkAtoms::option)) {
5039 return false;
5040 }
5041
5042 // Allow native anonymous content no matter what.
5043 if (aChild.IsRootOfNativeAnonymousSubtree()) {
5044 return false;
5045 }
5046
5047 // Options with labels have their label text added in ::before by forms.css.
5048 // Suppress frames for their child text.
5049 if (aParent->IsHTMLElement(nsGkAtoms::option)) {
5050 return aParent->AsElement()->HasNonEmptyAttr(nsGkAtoms::label);
5051 }
5052
5053 // If we're in any display: contents subtree, just suppress the frame.
5054 //
5055 // We can't be regular NAC, since display: contents has no frame to generate
5056 // them off.
5057 if (aChild.GetParent() != aParent) {
5058 return true;
5059 }
5060
5061 // Option is always fine.
5062 if (aChild.IsHTMLElement(nsGkAtoms::option)) {
5063 return false;
5064 }
5065
5066 // <optgroup> is OK in <select> but not in <optgroup>.
5067 if (aChild.IsHTMLElement(nsGkAtoms::optgroup) &&
5068 aParent->IsHTMLElement(nsGkAtoms::select)) {
5069 return false;
5070 }
5071
5072 // Anything else is not ok.
5073 return true;
5074}
5075
5076const nsCSSFrameConstructor::FrameConstructionData*
5077nsCSSFrameConstructor::FindDataForContent(nsIContent& aContent,
5078 ComputedStyle& aStyle,
5079 nsIFrame* aParentFrame,
5080 ItemFlags aFlags) {
5081 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"
, 5083); 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) = 5083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5082 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"
, 5083); 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) = 5083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5083 "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"
, 5083); 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) = 5083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5084
5085 if (auto* text = Text::FromNode(aContent)) {
5086 return FindTextData(*text, aParentFrame);
5087 }
5088
5089 return FindElementData(*aContent.AsElement(), aStyle, aParentFrame, aFlags);
5090}
5091
5092const nsCSSFrameConstructor::FrameConstructionData*
5093nsCSSFrameConstructor::FindElementData(const Element& aElement,
5094 ComputedStyle& aStyle,
5095 nsIFrame* aParentFrame,
5096 ItemFlags aFlags) {
5097 // Don't create frames for non-SVG element children of SVG elements.
5098 if (!aElement.IsSVGElement()) {
5099 if (aParentFrame && IsFrameForSVG(aParentFrame) &&
5100 !aParentFrame->IsSVGForeignObjectFrame()) {
5101 return nullptr;
5102 }
5103 if (aFlags.contains(ItemFlag::IsWithinSVGText)) {
5104 return nullptr;
5105 }
5106 }
5107
5108 if (auto* data = FindElementTagData(aElement, aStyle, aParentFrame, aFlags)) {
5109 return data;
5110 }
5111
5112 // Check for 'content: <image-url>' on the element (which makes us ignore
5113 // 'display' values other than 'none' or 'contents').
5114 if (nsImageFrame::ShouldCreateImageFrameForContentProperty(aElement,
5115 aStyle)) {
5116 static constexpr FrameConstructionData sImgData(
5117 NS_NewImageFrameForContentProperty);
5118 return &sImgData;
5119 }
5120
5121 const bool shouldBlockify = aFlags.contains(ItemFlag::IsForRenderedLegend) ||
5122 aFlags.contains(ItemFlag::IsForOutsideMarker);
5123 if (shouldBlockify && !aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
5124 // Make a temp copy of StyleDisplay and blockify its mDisplay value.
5125 auto display = *aStyle.StyleDisplay();
5126 bool isRootElement = false;
5127 uint16_t rawDisplayValue =
5128 Servo_ComputedValues_BlockifiedDisplay(&aStyle, isRootElement);
5129 display.mDisplay = StyleDisplay{rawDisplayValue};
5130 return FindDisplayData(display, aElement);
5131 }
5132
5133 const auto& display = *aStyle.StyleDisplay();
5134 return FindDisplayData(display, aElement);
5135}
5136
5137const nsCSSFrameConstructor::FrameConstructionData*
5138nsCSSFrameConstructor::FindElementTagData(const Element& aElement,
5139 ComputedStyle& aStyle,
5140 nsIFrame* aParentFrame,
5141 ItemFlags aFlags) {
5142 switch (aElement.GetNameSpaceID()) {
5143 case kNameSpaceID_XHTML3:
5144 return FindHTMLData(aElement, aParentFrame, aStyle);
5145 case kNameSpaceID_MathML6:
5146 return FindMathMLData(aElement, aStyle);
5147 case kNameSpaceID_SVG9:
5148 return FindSVGData(aElement, aParentFrame,
5149 aFlags.contains(ItemFlag::IsWithinSVGText),
5150 aFlags.contains(ItemFlag::AllowTextPathChild), aStyle);
5151 case kNameSpaceID_XUL8:
5152 return FindXULTagData(aElement, aStyle);
5153 default:
5154 return nullptr;
5155 }
5156}
5157
5158void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
5159 nsFrameConstructorState& aState, nsIContent* aContent,
5160 nsContainerFrame* aParentFrame, bool aSuppressWhiteSpaceOptimizations,
5161 ComputedStyle* aComputedStyle, ItemFlags aFlags,
5162 FrameConstructionItemList& aItems) {
5163 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"
, 5164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5164; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5164 "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"
, 5164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5164; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5165 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"
, 5165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsInComposedDoc()"
")"); do { *((volatile int*)__null) = 5165; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5166 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"
, 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5167 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"
, 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5167; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5168
5169 const bool withinSVGText = aFlags.contains(ItemFlag::IsWithinSVGText);
5170 const bool isGeneratedContent = aFlags.contains(ItemFlag::IsGeneratedContent);
5171 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"
, 5172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5172; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5172 "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"
, 5172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5172; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5173
5174 FrameConstructionItem* item = nullptr;
5175 auto cleanupGeneratedContent = mozilla::MakeScopeExit([&]() {
5176 if (isGeneratedContent && !item) {
5177 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"
, 5179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5179; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5178 "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"
, 5179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5179; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5179 "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"
, 5179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5179; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5180 aContent->UnbindFromTree();
5181 }
5182 });
5183
5184 // 'display:none' elements never creates any frames at all.
5185 const nsStyleDisplay& display = *aComputedStyle->StyleDisplay();
5186 if (display.mDisplay == StyleDisplay::None) {
5187 return;
5188 }
5189
5190 if (display.mDisplay == StyleDisplay::Contents) {
5191 // See the mDisplay fixup code in StyleAdjuster::adjust.
5192 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"
, 5193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5193; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5193 "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"
, 5193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5193; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5194
5195 // FIXME(bug 1588477): <svg:text>'s TextNodeCorrespondenceRecorder has
5196 // trouble with everything that looks like display: contents.
5197 if (withinSVGText) {
5198 return;
5199 }
5200
5201 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5202 *aComputedStyle, PseudoStyleType::before,
5203 aItems);
5204
5205 FlattenedChildIterator iter(aContent);
5206 InsertionPoint insertion(aParentFrame, aContent);
5207 for (nsIContent* child = iter.GetNextChild(); child;
5208 child = iter.GetNextChild()) {
5209 AddFrameConstructionItems(aState, child, aSuppressWhiteSpaceOptimizations,
5210 *aComputedStyle, insertion, aItems, aFlags);
5211 }
5212 aItems.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
5213
5214 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5215 *aComputedStyle, PseudoStyleType::after, aItems);
5216 return;
5217 }
5218
5219 nsIContent* parent = aParentFrame ? aParentFrame->GetContent() : nullptr;
5220 if (ShouldSuppressFrameInSelect(parent, *aContent)) {
5221 return;
5222 }
5223
5224 if (aContent->IsHTMLElement(nsGkAtoms::legend) && aParentFrame) {
5225 const nsFieldSetFrame* const fs = GetFieldSetFrameFor(aParentFrame);
5226 if (fs && !fs->GetLegend() && !aState.mHasRenderedLegend &&
5227 !aComputedStyle->StyleDisplay()->IsFloatingStyle() &&
5228 !aComputedStyle->StyleDisplay()->IsAbsolutelyPositionedStyle()) {
5229 aState.mHasRenderedLegend = true;
5230 aFlags += ItemFlag::IsForRenderedLegend;
5231 }
5232 }
5233
5234 const FrameConstructionData* const data =
5235 FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
5236 if (!data || data->mBits & FCDATA_SUPPRESS_FRAME0x40) {
5237 return;
5238 }
5239
5240 const bool isPopup = data->mBits & FCDATA_IS_POPUP0x100;
5241
5242 const uint32_t bits = data->mBits;
5243
5244 // Inside colgroups, suppress everything except columns.
5245 if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
5246 (!(bits & FCDATA_IS_TABLE_PART0x800) ||
5247 display.mDisplay != StyleDisplay::TableColumn)) {
5248 return;
5249 }
5250
5251 const bool canHavePageBreak =
5252 aFlags.contains(ItemFlag::AllowPageBreak) &&
5253 aState.mPresContext->IsPaginated() &&
5254 !display.IsAbsolutelyPositionedStyle() &&
5255 !(aParentFrame && aParentFrame->IsFlexOrGridContainer()) &&
5256 !(bits & FCDATA_IS_TABLE_PART0x800) && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5257 if (canHavePageBreak && display.BreakBefore()) {
5258 AppendPageBreakItem(aContent, aItems);
5259 }
5260
5261 if (!item) {
5262 item = aItems.AppendItem(this, data, aContent, do_AddRef(aComputedStyle),
5263 aSuppressWhiteSpaceOptimizations);
5264 if (aFlags.contains(ItemFlag::IsForRenderedLegend)) {
5265 item->mIsRenderedLegend = true;
5266 }
5267 }
5268 item->mIsText = !aContent->IsElement();
5269 item->mIsGeneratedContent = isGeneratedContent;
5270 if (isGeneratedContent) {
5271 // We need to keep this alive until the frame takes ownership.
5272 // This corresponds to the Release in ConstructFramesFromItem.
5273 item->mContent->AddRef();
5274 }
5275 item->mIsPopup = isPopup;
5276
5277 if (canHavePageBreak && display.BreakAfter()) {
5278 AppendPageBreakItem(aContent, aItems);
5279 }
5280
5281 if (bits & FCDATA_IS_INLINE0x1000) {
5282 // To correctly set item->mIsAllInline we need to build up our child items
5283 // right now.
5284 BuildInlineChildItems(aState, *item,
5285 aFlags.contains(ItemFlag::IsWithinSVGText),
5286 aFlags.contains(ItemFlag::AllowTextPathChild));
5287 item->mIsBlock = false;
5288 } else {
5289 // Compute a boolean isInline which is guaranteed to be false for blocks
5290 // (but may also be false for some inlines).
5291 const bool isInline =
5292 // Table-internal things are inline-outside if and only if they're kids
5293 // of inlines, since they'll trigger construction of inline-table
5294 // pseudos.
5295 ((bits & FCDATA_IS_TABLE_PART0x800) &&
5296 (!aParentFrame || // No aParentFrame means inline
5297 aParentFrame->StyleDisplay()->IsInlineFlow())) ||
5298 // Things that are inline-outside but aren't inline frames are inline
5299 display.IsInlineOutsideStyle() ||
5300 // Popups that are certainly out of flow.
5301 isPopup;
5302
5303 // Set mIsAllInline conservatively. It just might be that even an inline
5304 // that has mIsAllInline false doesn't need an {ib} split. So this is just
5305 // an optimization to keep from doing too much work in cases when we can
5306 // show that mIsAllInline is true..
5307 item->mIsAllInline =
5308 isInline ||
5309 // Figure out whether we're guaranteed this item will be out of flow.
5310 // This is not a precise test, since one of our ancestor inlines might
5311 // add an absolute containing block (if it's relatively positioned) when
5312 // there wasn't such a containing block before. But it's conservative
5313 // in the sense that anything that will really end up as an in-flow
5314 // non-inline will test false here. In other words, if this test is
5315 // true we're guaranteed to be inline; if it's false we don't know what
5316 // we'll end up as.
5317 //
5318 // If we make this test precise, we can remove some of the code dealing
5319 // with the imprecision in ConstructInline and adjust the comments on
5320 // mIsAllInline and mIsBlock in the header.
5321 (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
5322 aState.GetGeometricParent(display, nullptr));
5323
5324 // Set mIsBlock conservatively. It's OK to set it false for some real
5325 // blocks, but not OK to set it true for things that aren't blocks. Since
5326 // isOutOfFlow might be false even in cases when the frame will end up
5327 // out-of-flow, we can't use it here. But we _can_ say that the frame will
5328 // for sure end up in-flow if it's not floated or absolutely positioned.
5329 item->mIsBlock = !isInline && !display.IsAbsolutelyPositionedStyle() &&
5330 !display.IsFloatingStyle() && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5331 }
5332
5333 if (item->mIsAllInline) {
5334 aItems.InlineItemAdded();
5335 } else if (item->mIsBlock) {
5336 aItems.BlockItemAdded();
5337 }
5338}
5339
5340/**
5341 * Return true if the frame construction item pointed to by aIter will
5342 * create a frame adjacent to a line boundary in the frame tree, and that
5343 * line boundary is induced by a content node adjacent to the frame's
5344 * content node in the content tree. The latter condition is necessary so
5345 * that ContentAppended/ContentInserted/ContentRemoved can easily find any
5346 * text nodes that were suppressed here.
5347 */
5348bool nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter) {
5349 if (aIter.item().mSuppressWhiteSpaceOptimizations) {
5350 return false;
5351 }
5352
5353 if (aIter.AtStart()) {
5354 if (aIter.List()->HasLineBoundaryAtStart() &&
5355 !aIter.item().mContent->GetPreviousSibling())
5356 return true;
5357 } else {
5358 FCItemIterator prev = aIter;
5359 prev.Prev();
5360 if (prev.item().IsLineBoundary() &&
5361 !prev.item().mSuppressWhiteSpaceOptimizations &&
5362 aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
5363 return true;
5364 }
5365
5366 FCItemIterator next = aIter;
5367 next.Next();
5368 if (next.IsDone()) {
5369 if (aIter.List()->HasLineBoundaryAtEnd() &&
5370 !aIter.item().mContent->GetNextSibling())
5371 return true;
5372 } else {
5373 if (next.item().IsLineBoundary() &&
5374 !next.item().mSuppressWhiteSpaceOptimizations &&
5375 aIter.item().mContent->GetNextSibling() == next.item().mContent)
5376 return true;
5377 }
5378
5379 return false;
5380}
5381
5382void nsCSSFrameConstructor::ConstructFramesFromItem(
5383 nsFrameConstructorState& aState, FCItemIterator& aIter,
5384 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
5385 FrameConstructionItem& item = aIter.item();
5386 ComputedStyle* computedStyle = item.mComputedStyle;
5387 if (item.mIsText) {
5388 // If this is collapsible whitespace next to a line boundary,
5389 // don't create a frame. item.IsWhitespace() also sets the
5390 // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
5391 // end up creating a frame, nsTextFrame::Init will clear the flag.)
5392 // We don't do this for generated content, because some generated
5393 // text content is empty text nodes that are about to be initialized.
5394 // (We check mAdditionalStateBits because only the generated content
5395 // container's frame construction item is marked with
5396 // mIsGeneratedContent, and we might not have an aParentFrame.)
5397 // We don't do it for content that may have Shadow DOM siblings / insertion
5398 // points, because they make it difficult to correctly create the frame due
5399 // to dynamic changes.
5400 // We don't do it for SVG text, since we might need to position and
5401 // measure the white space glyphs due to x/y/dx/dy attributes.
5402 if (AtLineBoundary(aIter) &&
5403 !computedStyle->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
5404 aIter.List()->ParentHasNoShadowDOM() &&
5405 !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
5406 (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) &&
5407 !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT0x80000) &&
5408 !mAlwaysCreateFramesForIgnorableWhitespace && item.IsWhitespace(aState))
5409 return;
5410
5411 ConstructTextFrame(item.mFCData, aState, item.mContent, aParentFrame,
5412 computedStyle, aFrameList);
5413 return;
5414 }
5415
5416 AutoRestore<nsFrameState> savedStateBits(aState.mAdditionalStateBits);
5417 if (item.mIsGeneratedContent) {
5418 // Ensure that frames created here are all tagged with
5419 // NS_FRAME_GENERATED_CONTENT.
5420 aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
5421 }
5422
5423 // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
5424 ConstructFrameFromItemInternal(item, aState, aParentFrame, aFrameList);
5425
5426 if (item.mIsGeneratedContent) {
5427 // This corresponds to the AddRef in AddFrameConstructionItemsInternal.
5428 // The frame owns the generated content now.
5429 item.mContent->Release();
5430
5431 // Now that we've passed ownership of item.mContent to the frame, unset
5432 // our generated content flag so we don't release or unbind it ourselves.
5433 item.mIsGeneratedContent = false;
5434 }
5435}
5436
5437nsContainerFrame* nsCSSFrameConstructor::GetAbsoluteContainingBlock(
5438 nsIFrame* aFrame, ContainingBlockType aType) {
5439 // Starting with aFrame, look for a frame that is absolutely positioned or
5440 // relatively positioned (and transformed, if aType is FIXED)
5441 for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
5442 if (frame->IsMathMLFrame()) {
5443 // If it's mathml, bail out -- no absolute positioning out from inside
5444 // mathml frames. Note that we don't make this part of the loop
5445 // condition because of the stuff at the end of this method...
5446 return nullptr;
5447 }
5448
5449 // Look for the ICB.
5450 if (aType == FIXED_POS) {
5451 LayoutFrameType t = frame->Type();
5452 if (t == LayoutFrameType::Viewport || t == LayoutFrameType::PageContent) {
5453 return static_cast<nsContainerFrame*>(frame);
5454 }
5455 }
5456
5457 // If the frame is positioned, we will probably return it as the containing
5458 // block (see the exceptions below). Otherwise, we'll start looking at the
5459 // parent frame, unless we're dealing with a scrollframe.
5460 // Scrollframes are special since they're not positioned, but their
5461 // scrolledframe might be. So, we need to check this special case to return
5462 // the correct containing block (the scrolledframe) in that case.
5463 // If we're looking for a fixed-pos containing block and the frame is
5464 // not transformed, skip it.
5465 if (!frame->IsAbsPosContainingBlock()) {
5466 continue;
5467 }
5468 if (aType == FIXED_POS && !frame->IsFixedPosContainingBlock()) {
5469 continue;
5470 }
5471 nsIFrame* absPosCBCandidate = frame;
5472 LayoutFrameType type = absPosCBCandidate->Type();
5473 if (type == LayoutFrameType::FieldSet) {
5474 absPosCBCandidate =
5475 static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
5476 if (!absPosCBCandidate) {
5477 continue;
5478 }
5479 type = absPosCBCandidate->Type();
5480 }
5481 if (type == LayoutFrameType::ScrollContainer) {
5482 ScrollContainerFrame* scrollContainerFrame =
5483 do_QueryFrame(absPosCBCandidate);
5484 absPosCBCandidate = scrollContainerFrame->GetScrolledFrame();
5485 if (!absPosCBCandidate) {
5486 continue;
5487 }
5488 type = absPosCBCandidate->Type();
5489 }
5490 // Only first continuations can be containing blocks.
5491 absPosCBCandidate = absPosCBCandidate->FirstContinuation();
5492 // Is the frame really an absolute container?
5493 if (!absPosCBCandidate->IsAbsoluteContainer()) {
5494 continue;
5495 }
5496
5497 // For tables, skip the inner frame and consider the table wrapper frame.
5498 if (type == LayoutFrameType::Table) {
5499 continue;
5500 }
5501 // For table wrapper frames, we can just return absPosCBCandidate.
5502 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"
, 5503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5503 "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"
, 5503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5504 return static_cast<nsContainerFrame*>(absPosCBCandidate);
5505 }
5506
5507 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"
, 5507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aType != FIXED_POS"
") (" "no ICB in this frame tree?" ")"); do { *((volatile int
*)__null) = 5507; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5508
5509 // It is possible for the search for the containing block to fail, because
5510 // no absolute container can be found in the parent chain. In those cases,
5511 // we fall back to the document element's containing block.
5512 return mDocElementContainingBlock;
5513}
5514
5515nsContainerFrame* nsCSSFrameConstructor::GetFloatContainingBlock(
5516 nsIFrame* aFrame) {
5517 // Starting with aFrame, look for a frame that is a float containing block.
5518 // If we hit a frame which prevents its descendants from floating, bail out.
5519 // The logic here needs to match the logic in MaybePushFloatContainingBlock().
5520 for (nsIFrame* containingBlock = aFrame;
5521 containingBlock && !ShouldSuppressFloatingOfDescendants(containingBlock);
5522 containingBlock = containingBlock->GetParent()) {
5523 if (containingBlock->IsFloatContainingBlock()) {
5524 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"
, 5525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5525; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5525 "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"
, 5525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5525; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5526 return static_cast<nsContainerFrame*>(containingBlock);
5527 }
5528 }
5529
5530 // If we didn't find a containing block, then there just isn't
5531 // one.... return null
5532 return nullptr;
5533}
5534
5535/**
5536 * This function will get the previous sibling to use for an append operation.
5537 *
5538 * It takes a parent frame (must not be null) and the next insertion sibling, if
5539 * the parent content is display: contents or has ::after content (may be null).
5540 */
5541static nsIFrame* FindAppendPrevSibling(nsIFrame* aParentFrame,
5542 nsIFrame* aNextSibling) {
5543 aParentFrame->DrainSelfOverflowList();
5544
5545 if (aNextSibling) {
5546 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"
, 5548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5548
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5547 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"
, 5548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5548
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5548 "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"
, 5548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5548
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5549 return aNextSibling->GetPrevSibling();
5550 }
5551
5552 return aParentFrame->PrincipalChildList().LastChild();
5553}
5554
5555/**
5556 * Finds the right parent frame to append content to aParentFrame.
5557 *
5558 * Cannot return or receive null.
5559 */
5560static nsContainerFrame* ContinuationToAppendTo(
5561 nsContainerFrame* aParentFrame) {
5562 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"
, 5562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 5562; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5563
5564 if (IsFramePartOfIBSplit(aParentFrame)) {
5565 // If the frame we are manipulating is a ib-split frame (that is, one that's
5566 // been created as a result of a block-in-inline situation) then we need to
5567 // append to the last ib-split sibling, not to the frame itself.
5568 //
5569 // Always make sure to look at the last continuation of the frame for the
5570 // {ib} case, even if that continuation is empty.
5571 //
5572 // We don't do this for the non-ib-split-frame case, since in the other
5573 // cases appending to the last nonempty continuation is fine and in fact not
5574 // doing that can confuse code that doesn't know to pull kids from
5575 // continuations other than its next one.
5576 return static_cast<nsContainerFrame*>(
5577 GetLastIBSplitSibling(aParentFrame)->LastContinuation());
5578 }
5579
5580 return nsLayoutUtils::LastContinuationWithChild(aParentFrame);
5581}
5582
5583/**
5584 * This function will get the next sibling for a frame insert operation given
5585 * the parent and previous sibling. aPrevSibling may be null.
5586 */
5587static nsIFrame* GetInsertNextSibling(nsIFrame* aParentFrame,
5588 nsIFrame* aPrevSibling) {
5589 if (aPrevSibling) {
5590 return aPrevSibling->GetNextSibling();
5591 }
5592
5593 return aParentFrame->PrincipalChildList().FirstChild();
5594}
5595
5596void nsCSSFrameConstructor::AppendFramesToParent(
5597 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
5598 nsFrameList& aFrameList, nsIFrame* aPrevSibling, bool aIsRecursiveCall) {
5599 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"
, 5602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5600 !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"
, 5602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5601 !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"
, 5602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5602 "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"
, 5602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5602; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5603 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"
, 5604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5604; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5604 "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"
, 5604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5604; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5605 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"
, 5609); 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
) = 5609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5606 !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"
, 5609); 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
) = 5609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5607 !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"
, 5609); 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
) = 5609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5608 "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"
, 5609); 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
) = 5609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5609 "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"
, 5609); 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
) = 5609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
5610
5611 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
5612
5613 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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
5614 !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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
5615 ->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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
5616 .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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
5617 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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
5618 "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"
, 5618); MOZ_PretendNoReturn(); } } while (0)
;
5619 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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
5620 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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
5621 (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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
5622 !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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
5623 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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
5624 "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"
, 5624); MOZ_PretendNoReturn(); } } while (0)
;
5625
5626 // If we're inserting a list of frames at the end of the trailing inline
5627 // of an {ib} split, we may need to create additional {ib} siblings to parent
5628 // them.
5629 if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
5630 // When we get here, our frame list might start with a block. If it does
5631 // so, and aParentFrame is an inline, and it and all its previous
5632 // continuations have no siblings, then put the initial blocks from the
5633 // frame list into the previous block of the {ib} split. Note that we
5634 // didn't want to stop at the block part of the split when figuring out
5635 // initial parent, because that could screw up float parenting; it's easier
5636 // to do this little fixup here instead.
5637 if (aFrameList.NotEmpty() && aFrameList.FirstChild()->IsBlockOutside()) {
5638 // See whether our trailing inline is empty
5639 nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
5640 if (firstContinuation->PrincipalChildList().IsEmpty()) {
5641 // Our trailing inline is empty. Collect our starting blocks from
5642 // aFrameList, get the right parent frame for them, and put them in.
5643 nsFrameList blockKids =
5644 aFrameList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
5645 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"
, 5645); MOZ_PretendNoReturn(); } } while (0)
;
5646
5647 nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
5648 prevBlock =
5649 static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
5650 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"
, 5650); MOZ_PretendNoReturn(); } } while (0)
;
5651
5652 MoveChildrenTo(aParentFrame, prevBlock, blockKids);
5653 }
5654 }
5655
5656 // We want to put some of the frames into this inline frame.
5657 nsFrameList inlineKids =
5658 aFrameList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
5659
5660 if (!inlineKids.IsEmpty()) {
5661 AppendFrames(aParentFrame, FrameChildListID::Principal,
5662 std::move(inlineKids));
5663 }
5664
5665 if (!aFrameList.IsEmpty()) {
5666 nsFrameList ibSiblings;
5667 CreateIBSiblings(aState, aParentFrame,
5668 aParentFrame->IsAbsPosContainingBlock(), aFrameList,
5669 ibSiblings);
5670
5671 // Make sure to trigger reflow of the inline that used to be our
5672 // last one and now isn't anymore, since its GetSkipSides() has
5673 // changed.
5674 mPresShell->FrameNeedsReflow(aParentFrame,
5675 IntrinsicDirty::FrameAndAncestors,
5676 NS_FRAME_HAS_DIRTY_CHILDREN);
5677
5678 // Recurse so we create new ib siblings as needed for aParentFrame's
5679 // parent
5680 return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
5681 aParentFrame, true);
5682 }
5683 return;
5684 }
5685
5686 // If we're appending a list of frames to the last continuations of a
5687 // ::-moz-column-content, we may need to create column-span siblings for them.
5688 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
5689 // Extract any initial non-column-span kids, and append them to
5690 // ::-moz-column-content's child list.
5691 nsFrameList initialNonColumnSpanKids =
5692 aFrameList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
5693 AppendFrames(aParentFrame, FrameChildListID::Principal,
5694 std::move(initialNonColumnSpanKids));
5695
5696 if (aFrameList.IsEmpty()) {
5697 // No more kids to process (there weren't any column-span kids).
5698 return;
5699 }
5700
5701 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
5702 aState, aParentFrame, aFrameList,
5703 // Column content should never be a absolute/fixed positioned containing
5704 // block. Pass nullptr as aPositionedFrame.
5705 nullptr);
5706
5707 nsContainerFrame* columnSetWrapper = aParentFrame->GetParent();
5708 while (!columnSetWrapper->IsColumnSetWrapperFrame()) {
5709 columnSetWrapper = columnSetWrapper->GetParent();
5710 }
5711 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"
, 5712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5712; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5712 "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"
, 5712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5712; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5713
5714 FinishBuildingColumns(aState, columnSetWrapper, aParentFrame,
5715 columnSpanSiblings);
5716
5717 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"
, 5718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5718; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5718 "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"
, 5718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5718; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5719 return;
5720 }
5721
5722 // Insert the frames after our aPrevSibling
5723 InsertFrames(aParentFrame, FrameChildListID::Principal, aPrevSibling,
5724 std::move(aFrameList));
5725}
5726
5727// This gets called to see if the frames corresponding to aSibling and aContent
5728// should be siblings in the frame tree. Although (1) rows and cols, (2) row
5729// groups and col groups, (3) row groups and captions, (4) legends and content
5730// inside fieldsets, (5) popups and other kids of the menu are siblings from a
5731// content perspective, they are not considered siblings in the frame tree.
5732bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
5733 nsIContent* aContent,
5734 Maybe<StyleDisplay>& aDisplay) {
5735 StyleDisplay siblingDisplay = aSibling->GetDisplay();
5736 if (StyleDisplay::TableColumnGroup == siblingDisplay ||
5737 StyleDisplay::TableColumn == siblingDisplay ||
5738 StyleDisplay::TableCaption == siblingDisplay ||
5739 StyleDisplay::TableHeaderGroup == siblingDisplay ||
5740 StyleDisplay::TableRowGroup == siblingDisplay ||
5741 StyleDisplay::TableFooterGroup == siblingDisplay) {
5742 // if we haven't already, resolve a style to find the display type of
5743 // aContent.
5744 if (aDisplay.isNothing()) {
5745 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
5746 // Comments and processing instructions never have frames, so we should
5747 // not try to generate styles for them.
5748 return false;
5749 }
5750 // FIXME(emilio): This is buggy some times, see bug 1424656.
5751 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5752 const nsStyleDisplay* display = computedStyle->StyleDisplay();
5753 aDisplay.emplace(display->mDisplay);
5754 }
5755
5756 StyleDisplay display = aDisplay.value();
5757 // To have decent performance we want to return false in cases in which
5758 // reordering the two siblings has no effect on display. To ensure
5759 // correctness, we MUST return false in cases where the two siblings have
5760 // the same desired parent type and live on different display lists.
5761 // Specificaly, columns and column groups should only consider columns and
5762 // column groups as valid siblings. Captions should only consider other
5763 // captions. All other things should consider each other as valid
5764 // siblings. The restriction in the |if| above on siblingDisplay is ok,
5765 // because for correctness the only part that really needs to happen is to
5766 // not consider captions, column groups, and row/header/footer groups
5767 // siblings of each other. Treating a column or colgroup as a valid
5768 // sibling of a non-table-related frame will just mean we end up reframing.
5769 if ((siblingDisplay == StyleDisplay::TableCaption) !=
5770 (display == StyleDisplay::TableCaption)) {
5771 // One's a caption and the other is not. Not valid siblings.
5772 return false;
5773 }
5774
5775 if ((siblingDisplay == StyleDisplay::TableColumnGroup ||
5776 siblingDisplay == StyleDisplay::TableColumn) !=
5777 (display == StyleDisplay::TableColumnGroup ||
5778 display == StyleDisplay::TableColumn)) {
5779 // One's a column or column group and the other is not. Not valid
5780 // siblings.
5781 return false;
5782 }
5783 // Fall through; it's possible that the display type was overridden and
5784 // a different sort of frame was constructed, so we may need to return false
5785 // below.
5786 }
5787
5788 return true;
5789}
5790
5791// FIXME(emilio): If we ever kill IsValidSibling() we can simplify this quite a
5792// bit (no need to pass aTargetContent or aTargetContentDisplay, and the
5793// adjust() calls can be responsibility of the caller).
5794template <nsCSSFrameConstructor::SiblingDirection aDirection>
5795nsIFrame* nsCSSFrameConstructor::FindSiblingInternal(
5796 FlattenedChildIterator& aIter, nsIContent* aTargetContent,
5797 Maybe<StyleDisplay>& aTargetContentDisplay) {
5798 auto adjust = [&](nsIFrame* aPotentialSiblingFrame) -> nsIFrame* {
5799 return AdjustSiblingFrame(aPotentialSiblingFrame, aTargetContent,
5800 aTargetContentDisplay, aDirection);
5801 };
5802
5803 auto nextDomSibling = [](FlattenedChildIterator& aIter) -> nsIContent* {
5804 return aDirection == SiblingDirection::Forward ? aIter.GetNextChild()
5805 : aIter.GetPreviousChild();
5806 };
5807
5808 auto getInsideMarkerFrame = [](const nsIContent* aContent) -> nsIFrame* {
5809 auto* marker = nsLayoutUtils::GetMarkerFrame(aContent);
5810 const bool isInsideMarker =
5811 marker && marker->GetInFlowParent()->StyleList()->mListStylePosition ==
5812 StyleListStylePosition::Inside;
5813 return isInsideMarker ? marker : nullptr;
5814 };
5815
5816 auto getNearPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5817 if (aDirection == SiblingDirection::Forward) {
5818 if (auto* marker = getInsideMarkerFrame(aContent)) {
5819 return marker;
5820 }
5821 return nsLayoutUtils::GetBeforeFrame(aContent);
5822 }
5823 return nsLayoutUtils::GetAfterFrame(aContent);
5824 };
5825
5826 auto getFarPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5827 if (aDirection == SiblingDirection::Forward) {
5828 return nsLayoutUtils::GetAfterFrame(aContent);
5829 }
5830 if (auto* before = nsLayoutUtils::GetBeforeFrame(aContent)) {
5831 return before;
5832 }
5833 return getInsideMarkerFrame(aContent);
5834 };
5835
5836 while (nsIContent* sibling = nextDomSibling(aIter)) {
5837 // NOTE(emilio): It's important to check GetPrimaryFrame() before
5838 // IsDisplayContents to get the correct insertion point when multiple
5839 // siblings go from display: non-none to display: contents.
5840 if (nsIFrame* primaryFrame = sibling->GetPrimaryFrame()) {
5841 // XXX the GetContent() == sibling check is needed due to bug 135040.
5842 // Remove it once that's fixed.
5843 if (primaryFrame->GetContent() == sibling) {
5844 if (nsIFrame* frame = adjust(primaryFrame)) {
5845 return frame;
5846 }
5847 }
5848 }
5849
5850 if (IsDisplayContents(sibling)) {
5851 if (nsIFrame* frame = adjust(getNearPseudo(sibling))) {
5852 return frame;
5853 }
5854
5855 const bool startFromBeginning = aDirection == SiblingDirection::Forward;
5856 FlattenedChildIterator iter(sibling, startFromBeginning);
5857 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5858 iter, aTargetContent, aTargetContentDisplay);
5859 if (sibling) {
5860 return sibling;
5861 }
5862 }
5863 }
5864
5865 return adjust(getFarPseudo(aIter.Parent()));
5866}
5867
5868nsIFrame* nsCSSFrameConstructor::AdjustSiblingFrame(
5869 nsIFrame* aSibling, nsIContent* aTargetContent,
5870 Maybe<StyleDisplay>& aTargetContentDisplay, SiblingDirection aDirection) {
5871 if (!aSibling) {
5872 return nullptr;
5873 }
5874
5875 if (aSibling->IsRenderedLegend()) {
5876 return nullptr;
5877 }
5878
5879 if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
5880 aSibling = aSibling->GetPlaceholderFrame();
5881 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"
, 5881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSibling" ")"
); do { *((volatile int*)__null) = 5881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5882 }
5883
5884 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"
, 5884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aSibling->GetPrevContinuation()"
") (" "How?" ")"); do { *((volatile int*)__null) = 5884; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5885 if (aDirection == SiblingDirection::Backward) {
5886 // The frame may be a ib-split frame (a split inline frame that contains a
5887 // block). Get the last part of that split.
5888 if (IsFramePartOfIBSplit(aSibling)) {
5889 aSibling = GetLastIBSplitSibling(aSibling);
5890 }
5891
5892 // The frame may have a continuation. If so, we want the last
5893 // non-overflow-container continuation as our previous sibling.
5894 aSibling = aSibling->GetTailContinuation();
5895 }
5896
5897 if (!IsValidSibling(aSibling, aTargetContent, aTargetContentDisplay)) {
5898 return nullptr;
5899 }
5900
5901 return aSibling;
5902}
5903
5904nsIFrame* nsCSSFrameConstructor::FindPreviousSibling(
5905 const FlattenedChildIterator& aIter,
5906 Maybe<StyleDisplay>& aTargetContentDisplay) {
5907 return FindSibling<SiblingDirection::Backward>(aIter, aTargetContentDisplay);
5908}
5909
5910nsIFrame* nsCSSFrameConstructor::FindNextSibling(
5911 const FlattenedChildIterator& aIter,
5912 Maybe<StyleDisplay>& aTargetContentDisplay) {
5913 return FindSibling<SiblingDirection::Forward>(aIter, aTargetContentDisplay);
5914}
5915
5916template <nsCSSFrameConstructor::SiblingDirection aDirection>
5917nsIFrame* nsCSSFrameConstructor::FindSibling(
5918 const FlattenedChildIterator& aIter,
5919 Maybe<StyleDisplay>& aTargetContentDisplay) {
5920 nsIContent* targetContent = aIter.Get();
5921 FlattenedChildIterator siblingIter = aIter;
5922 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5923 siblingIter, targetContent, aTargetContentDisplay);
5924 if (sibling) {
5925 return sibling;
5926 }
5927
5928 // Our siblings (if any) do not have a frame to guide us. The frame for the
5929 // target content should be inserted whereever a frame for the container would
5930 // be inserted. This is needed when inserting into display: contents nodes.
5931 const nsIContent* current = aIter.Parent();
5932 while (IsDisplayContents(current)) {
5933 const nsIContent* parent = current->GetFlattenedTreeParent();
5934 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"
, 5934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"No display: contents on the root" ")"); do { *((volatile int
*)__null) = 5934; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5935
5936 FlattenedChildIterator iter(parent);
5937 iter.Seek(current);
5938 sibling = FindSiblingInternal<aDirection>(iter, targetContent,
5939 aTargetContentDisplay);
5940 if (sibling) {
5941 return sibling;
5942 }
5943
5944 current = parent;
5945 }
5946
5947 return nullptr;
5948}
5949
5950// For fieldsets, returns the area frame, if the child is not a legend.
5951static nsContainerFrame* GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
5952 nsIContent* aChildContent) {
5953 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"
, 5953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->IsTableWrapperFrame()"
") (" "Shouldn't be happening!" ")"); do { *((volatile int*)
__null) = 5953; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5954
5955 nsContainerFrame* newParent = nullptr;
5956 if (aParentFrame->IsFieldSetFrame()) {
5957 // If the parent is a fieldSet, use the fieldSet's area frame as the
5958 // parent unless the new content is a legend.
5959 if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
5960 newParent = static_cast<nsFieldSetFrame*>(aParentFrame)->GetInner();
5961 if (newParent) {
5962 newParent = newParent->GetContentInsertionFrame();
5963 }
5964 }
5965 }
5966 return newParent ? newParent : aParentFrame;
5967}
5968
5969nsIFrame* nsCSSFrameConstructor::GetInsertionPrevSibling(
5970 InsertionPoint* aInsertion, nsIContent* aChild, bool* aIsAppend,
5971 bool* aIsRangeInsertSafe, nsIContent* aStartSkipChild,
5972 nsIContent* aEndSkipChild) {
5973 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"
, 5973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertion->mParentFrame"
") (" "Must have parent frame to start with" ")"); do { *((volatile
int*)__null) = 5973; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5974
5975 *aIsAppend = false;
5976
5977 // Find the frame that precedes the insertion point.
5978 FlattenedChildIterator iter(aInsertion->mContainer);
5979 if (!aChild->IsRootOfNativeAnonymousSubtree()) {
5980 // The check for IsRootOfNativeAnonymousSubtree() is because editor is
5981 // severely broken and calls us directly for native anonymous
5982 // nodes that it creates.
5983 if (aStartSkipChild) {
5984 iter.Seek(aStartSkipChild);
5985 } else {
5986 iter.Seek(aChild);
5987 }
5988 } else {
5989 // Prime the iterator for the call to FindPreviousSibling.
5990 iter.GetNextChild();
5991 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"
, 5993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5993; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5992 "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"
, 5993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5993; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5993 "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"
, 5993); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5993; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5994 }
5995
5996 // Note that FindPreviousSibling is passed the iterator by value, so that
5997 // the later usage of the iterator starts from the same place.
5998 Maybe<StyleDisplay> childDisplay;
5999 nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay);
6000
6001 // Now, find the geometric parent so that we can handle
6002 // continuations properly. Use the prev sibling if we have it;
6003 // otherwise use the next sibling.
6004 if (prevSibling) {
6005 aInsertion->mParentFrame =
6006 prevSibling->GetParent()->GetContentInsertionFrame();
6007 } else {
6008 // If there is no previous sibling, then find the frame that follows
6009 //
6010 // FIXME(emilio): This is really complex and probably shouldn't be.
6011 if (aEndSkipChild) {
6012 iter.Seek(aEndSkipChild);
6013 iter.GetPreviousChild();
6014 }
6015 if (nsIFrame* nextSibling = FindNextSibling(iter, childDisplay)) {
6016 aInsertion->mParentFrame =
6017 nextSibling->GetParent()->GetContentInsertionFrame();
6018 } else {
6019 // No previous or next sibling, so treat this like an appended frame.
6020 *aIsAppend = true;
6021
6022 // Deal with fieldsets.
6023 aInsertion->mParentFrame =
6024 ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
6025
6026 aInsertion->mParentFrame =
6027 ::ContinuationToAppendTo(aInsertion->mParentFrame);
6028
6029 prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, nullptr);
6030 }
6031 }
6032
6033 *aIsRangeInsertSafe = childDisplay.isNothing();
6034 return prevSibling;
6035}
6036
6037nsContainerFrame* nsCSSFrameConstructor::GetContentInsertionFrameFor(
6038 nsIContent* aContent) {
6039 nsIFrame* frame;
6040 while (!(frame = aContent->GetPrimaryFrame())) {
6041 if (!IsDisplayContents(aContent)) {
6042 return nullptr;
6043 }
6044
6045 aContent = aContent->GetFlattenedTreeParent();
6046 if (!aContent) {
6047 return nullptr;
6048 }
6049 }
6050
6051 // If the content of the frame is not the desired content then this is not
6052 // really a frame for the desired content.
6053 // XXX This check is needed due to bug 135040. Remove it once that's fixed.
6054 if (frame->GetContent() != aContent) {
6055 return nullptr;
6056 }
6057
6058 nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
6059
6060 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"
, 6062); MOZ_PretendNoReturn(); } } while (0)
6061 "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"
, 6062); MOZ_PretendNoReturn(); } } while (0)
6062 "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"
, 6062); MOZ_PretendNoReturn(); } } while (0)
;
6063
6064 return insertionFrame;
6065}
6066
6067static bool IsSpecialFramesetChild(nsIContent* aContent) {
6068 // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
6069 return aContent->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame);
6070}
6071
6072static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode);
6073
6074void nsCSSFrameConstructor::AddTextItemIfNeeded(
6075 nsFrameConstructorState& aState, const ComputedStyle& aParentStyle,
6076 const InsertionPoint& aInsertion, nsIContent* aPossibleTextContent,
6077 FrameConstructionItemList& aItems) {
6078 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"
, 6078); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleTextContent"
") (" "Must have node" ")"); do { *((volatile int*)__null) =
6078; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
6079 if (!aPossibleTextContent->IsText() ||
6080 !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6081 aPossibleTextContent->HasFlag(NODE_NEEDS_FRAME)) {
6082 // Not text, or not suppressed due to being all-whitespace (if it were being
6083 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6084 // going to be reframed anyway.
6085 return;
6086 }
6087 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"
, 6088); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6088; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6088 "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"
, 6088); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6088; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6089 AddFrameConstructionItems(aState, aPossibleTextContent, false, aParentStyle,
6090 aInsertion, aItems);
6091}
6092
6093void nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aContent) {
6094 if (!aContent->IsText() ||
6095 !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6096 aContent->HasFlag(NODE_NEEDS_FRAME)) {
6097 // Not text, or not suppressed due to being all-whitespace (if it were being
6098 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6099 // going to be reframed anyway.
6100 return;
6101 }
6102 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"
, 6103); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6103; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6103 "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"
, 6103); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6103; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6104 ContentInserted(aContent, InsertionKind::Async);
6105}
6106
6107#ifdef DEBUG1
6108void nsCSSFrameConstructor::CheckBitsForLazyFrameConstruction(
6109 nsIContent* aParent) {
6110 // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
6111 // we want to assert, but leaf frames that process their own children and may
6112 // ignore anonymous children (eg framesets) make this complicated. So we set
6113 // these two booleans if we encounter these situations and unset them if we
6114 // hit a node with a leaf frame.
6115 //
6116 // It's fine if one of node without primary frame is in a display:none
6117 // subtree.
6118 //
6119 // Also, it's fine if one of the nodes without primary frame is a display:
6120 // contents node.
6121 bool noPrimaryFrame = false;
6122 bool needsFrameBitSet = false;
6123 nsIContent* content = aParent;
6124 while (content && !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
6125 if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
6126 noPrimaryFrame = needsFrameBitSet = false;
6127 }
6128 if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
6129 noPrimaryFrame = !IsDisplayContents(content);
6130 }
6131 if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
6132 needsFrameBitSet = true;
6133 }
6134
6135 content = content->GetFlattenedTreeParent();
6136 }
6137 if (content && content->GetPrimaryFrame() &&
6138 content->GetPrimaryFrame()->IsLeaf()) {
6139 noPrimaryFrame = needsFrameBitSet = false;
6140 }
6141 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"
, 6143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6142 "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"
, 6143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6143 "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"
, 6143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6144 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"
, 6146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6146; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6145 "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"
, 6146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6146; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6146 "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"
, 6146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6146; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6147}
6148#endif
6149
6150// Returns true if this operation can be lazy, false if not.
6151//
6152// FIXME(emilio, bug 1410020): This function assumes that the flattened tree
6153// parent of all the appended children is the same, which, afaict, is not
6154// necessarily true.
6155void nsCSSFrameConstructor::ConstructLazily(Operation aOperation,
6156 nsIContent* aChild) {
6157 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"
, 6157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParent()"
")"); do { *((volatile int*)__null) = 6157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6158
6159 // We can construct lazily; just need to set suitable bits in the content
6160 // tree.
6161 Element* parent = aChild->GetFlattenedTreeParentElement();
6162 if (!parent) {
6163 // Not part of the flat tree, nothing to do.
6164 return;
6165 }
6166
6167 if (Servo_Element_IsDisplayNone(parent)) {
6168 // Nothing to do either.
6169 //
6170 // FIXME(emilio): This should be an assert, except for weird <frameset>
6171 // stuff that does its own frame construction. Such an assert would fire in
6172 // layout/style/crashtests/1411478.html, for example.
6173 return;
6174 }
6175
6176 // Set NODE_NEEDS_FRAME on the new nodes.
6177 if (aOperation == CONTENTINSERT) {
6178 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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
6179 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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
6180 // 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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
6181 // 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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
6182 // 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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
6183 "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"
, 6183); MOZ_PretendNoReturn(); } } while (0)
;
6184 aChild->SetFlags(NODE_NEEDS_FRAME);
6185 } else { // CONTENTAPPEND
6186 for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
6187 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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
6188 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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
6189 // 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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
6190 // 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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
6191 // 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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
6192 "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"
, 6192); MOZ_PretendNoReturn(); } } while (0)
;
6193 child->SetFlags(NODE_NEEDS_FRAME);
6194 }
6195 }
6196
6197 CheckBitsForLazyFrameConstruction(parent);
6198 parent->NoteDescendantsNeedFramesForServo();
6199}
6200
6201void nsCSSFrameConstructor::IssueSingleInsertNofications(
6202 nsIContent* aStartChild, nsIContent* aEndChild,
6203 InsertionKind aInsertionKind) {
6204 for (nsIContent* child = aStartChild; child != aEndChild;
6205 child = child->GetNextSibling()) {
6206 // XXX the GetContent() != child check is needed due to bug 135040.
6207 // Remove it once that's fixed.
6208 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"
, 6209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6209; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6209 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"
, 6209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6209; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6210
6211 // Call ContentRangeInserted with this node.
6212 ContentRangeInserted(child, child->GetNextSibling(), aInsertionKind);
6213 }
6214}
6215
6216bool nsCSSFrameConstructor::InsertionPoint::IsMultiple() const {
6217 // Fieldset frames have multiple normal flow child frame lists so handle it
6218 // the same as if it had multiple content insertion points.
6219 return mParentFrame && mParentFrame->IsFieldSetFrame();
6220}
6221
6222nsCSSFrameConstructor::InsertionPoint
6223nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aStartChild,
6224 nsIContent* aEndChild,
6225 InsertionKind aInsertionKind) {
6226 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"
, 6226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
")"); do { *((volatile int*)__null) = 6226; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6227
6228 nsIContent* parent = aStartChild->GetParent();
6229 if (!parent) {
6230 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6231 return {};
6232 }
6233
6234 // If the children of the container may be distributed to different insertion
6235 // points, insert them separately and bail out, letting ContentInserted handle
6236 // the mess.
6237 if (parent->GetShadowRoot()) {
6238 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6239 return {};
6240 }
6241
6242#ifdef DEBUG1
6243 {
6244 nsIContent* expectedParent = aStartChild->GetFlattenedTreeParent();
6245 for (nsIContent* child = aStartChild->GetNextSibling(); child;
6246 child = child->GetNextSibling()) {
6247 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"
, 6247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child->GetFlattenedTreeParent() == expectedParent"
")"); do { *((volatile int*)__null) = 6247; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6248 }
6249 }
6250#endif
6251
6252 // Now the flattened tree parent of all the siblings is the same, just use the
6253 // same insertion point and take the fast path, unless it's a multiple
6254 // insertion point.
6255 InsertionPoint ip = GetInsertionPoint(aStartChild);
6256 if (ip.IsMultiple()) {
6257 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6258 return {};
6259 }
6260
6261 return ip;
6262}
6263
6264bool nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
6265 nsIContent* aStartChild,
6266 nsIContent* aEndChild) {
6267 if (aParentFrame->IsFrameSetFrame()) {
6268 // Check whether we have any kids we care about.
6269 for (nsIContent* cur = aStartChild; cur != aEndChild;
6270 cur = cur->GetNextSibling()) {
6271 if (IsSpecialFramesetChild(cur)) {
6272 // Just reframe the parent, since framesets are weird like that.
6273 RecreateFramesForContent(aParentFrame->GetContent(),
6274 InsertionKind::Async);
6275 return true;
6276 }
6277 }
6278 }
6279 return false;
6280}
6281
6282void nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild,
6283 nsIContent* aEndChild) {
6284 for (nsIContent* child = aStartChild; child != aEndChild;
6285 child = child->GetNextSibling()) {
6286 if (child->IsElement()) {
6287 child->AsElement()->NoteDirtyForServo();
6288 }
6289 }
6290}
6291
6292#ifdef DEBUG1
6293static bool IsFlattenedTreeChild(nsIContent* aParent, nsIContent* aChild) {
6294 FlattenedChildIterator iter(aParent);
6295 for (nsIContent* node = iter.GetNextChild(); node;
6296 node = iter.GetNextChild()) {
6297 if (node == aChild) {
6298 return true;
6299 }
6300 }
6301 return false;
6302}
6303#endif
6304
6305void nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
6306 nsIContent* aEndChild) {
6307 ServoStyleSet* styleSet = mPresShell->StyleSet();
6308
6309 for (nsIContent* child = aStartChild; child != aEndChild;
6310 child = child->GetNextSibling()) {
6311 if (!child->IsElement()) {
6312 continue;
6313 }
6314
6315 Element* childElement = child->AsElement();
6316
6317 // We only come in here from non-lazy frame construction, so the children
6318 // should be unstyled.
6319 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"
, 6319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!childElement->HasServoData()"
")"); do { *((volatile int*)__null) = 6319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6320
6321#ifdef DEBUG1
6322 {
6323 // Furthermore, all of them should have the same flattened tree parent
6324 // (GetRangeInsertionPoint ensures it). And that parent should be styled,
6325 // otherwise we would've never found an insertion point at all.
6326 Element* parent = childElement->GetFlattenedTreeParentElement();
6327 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"
, 6327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ")"
); do { *((volatile int*)__null) = 6327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6328 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"
, 6328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasServoData()"
")"); do { *((volatile int*)__null) = 6328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6329 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"
, 6331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6331; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6330 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"
, 6331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6331; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6331 "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"
, 6331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6331; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6332 }
6333#endif
6334
6335 styleSet->StyleNewSubtree(childElement);
6336 }
6337}
6338
6339nsIFrame* nsCSSFrameConstructor::FindNextSiblingForAppend(
6340 const InsertionPoint& aInsertion) {
6341 auto SlowPath = [&]() -> nsIFrame* {
6342 FlattenedChildIterator iter(aInsertion.mContainer,
6343 /* aStartAtBeginning = */ false);
6344 iter.GetPreviousChild(); // Prime the iterator.
6345 Maybe<StyleDisplay> unused;
6346 return FindNextSibling(iter, unused);
6347 };
6348
6349 if (!IsDisplayContents(aInsertion.mContainer) &&
6350 !nsLayoutUtils::GetAfterFrame(aInsertion.mContainer)) {
6351 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"
, 6351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!SlowPath()"
")"); do { *((volatile int*)__null) = 6351; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6352 return nullptr;
6353 }
6354
6355 return SlowPath();
6356}
6357
6358// This is a bit slow, but sometimes we need it.
6359static bool ParentIsWrapperAnonBox(nsIFrame* aParent) {
6360 nsIFrame* maybeAnonBox = aParent;
6361 if (maybeAnonBox->Style()->GetPseudoType() == PseudoStyleType::cellContent) {
6362 // The thing that would maybe be a wrapper anon box is the cell.
6363 maybeAnonBox = maybeAnonBox->GetParent();
6364 }
6365 return maybeAnonBox->Style()->IsWrapperAnonBox();
6366}
6367
6368void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
6369 InsertionKind aInsertionKind) {
6370 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"
, 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6371 !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"
, 6371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6372
6373 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentAppended",mozilla::AutoProfilerLabelHot raiiObject6374( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6374 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6374( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6375 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6376
6377#ifdef DEBUG1
6378 if (gNoisyContentUpdates) {
6379 printf(
6380 "nsCSSFrameConstructor::ContentAppended container=%p "
6381 "first-child=%p lazy=%d\n",
6382 aFirstNewContent->GetParent(), aFirstNewContent,
6383 aInsertionKind == InsertionKind::Async);
6384 if (gReallyNoisyContentUpdates && aFirstNewContent->GetParent()) {
6385 aFirstNewContent->GetParent()->List(stdoutstdout, 0);
6386 }
6387 }
6388
6389 for (nsIContent* child = aFirstNewContent; child;
6390 child = child->GetNextSibling()) {
6391 // XXX the GetContent() != child check is needed due to bug 135040.
6392 // Remove it once that's fixed.
6393 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"
, 6396); 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) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6394 !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"
, 6396); 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) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6395 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"
, 6396); 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) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6396 "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"
, 6396); 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) = 6396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6397 }
6398#endif
6399
6400 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6401 InsertionPoint insertion =
6402 GetRangeInsertionPoint(aFirstNewContent, nullptr, aInsertionKind);
6403 nsContainerFrame*& parentFrame = insertion.mParentFrame;
6404 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6405 if (!parentFrame) {
6406 // We're punting on frame construction because there's no container frame.
6407 // The Servo-backed style system handles this case like the lazy frame
6408 // construction case, except when we're already constructing frames, in
6409 // which case we shouldn't need to do anything else.
6410 if (aInsertionKind == InsertionKind::Async) {
6411 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6412 }
6413 return;
6414 }
6415
6416 if (aInsertionKind == InsertionKind::Async) {
6417 ConstructLazily(CONTENTAPPEND, aFirstNewContent);
6418 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6419 return;
6420 }
6421
6422 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6423 if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
6424 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6425 return;
6426 }
6427 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6428
6429 if (parentFrame->IsLeaf()) {
6430 // Nothing to do here; we shouldn't be constructing kids of leaves
6431 // Clear lazy bits so we don't try to construct again.
6432 ClearLazyBits(aFirstNewContent, nullptr);
6433 return;
6434 }
6435
6436 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6437 if (WipeInsertionParent(parentFrame)) {
6438 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6439 return;
6440 }
6441 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6442
6443#ifdef DEBUG1
6444 if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
6445 printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
6446 parentFrame->ListTag(stdoutstdout);
6447 printf(" is ib-split\n");
6448 }
6449#endif
6450
6451 // We should never get here with fieldsets, since they have
6452 // multiple insertion points.
6453 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"
, 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6454; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6454 "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"
, 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6454; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6455
6456 nsIFrame* nextSibling = FindNextSiblingForAppend(insertion);
6457 if (nextSibling) {
6458 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6459 } else {
6460 parentFrame = ::ContinuationToAppendTo(parentFrame);
6461 }
6462
6463 nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
6464
6465 // See if the containing block has :first-letter style applied.
6466 const bool haveFirstLetterStyle =
6467 containingBlock && HasFirstLetterStyle(containingBlock);
6468
6469 const bool haveFirstLineStyle =
6470 containingBlock && ShouldHaveFirstLineStyle(containingBlock->GetContent(),
6471 containingBlock->Style());
6472
6473 if (haveFirstLetterStyle) {
6474 AutoWeakFrame wf(nextSibling);
6475
6476 // Before we get going, remove the current letter frames
6477 RemoveLetterFrames(mPresShell, containingBlock);
6478
6479 // Reget nextSibling, since we may have killed it.
6480 //
6481 // FIXME(emilio): This kinda sucks! :(
6482 if (nextSibling && !wf) {
6483 nextSibling = FindNextSiblingForAppend(insertion);
6484 if (nextSibling) {
6485 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6486 containingBlock = GetFloatContainingBlock(parentFrame);
6487 }
6488 }
6489 }
6490
6491 // Create some new frames
6492 nsFrameConstructorState state(
6493 mPresShell, GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
6494 GetAbsoluteContainingBlock(parentFrame, ABS_POS), containingBlock);
6495
6496 if (mPresShell->GetPresContext()->IsPaginated()) {
6497 // Because this function can be called outside frame construction, we need
6498 // to set state.mAutoPageNameValue based on what the parent frame's auto
6499 // value is.
6500 // Calling this from outside the frame constructor can violate many of the
6501 // expectations in AutoFrameConstructionPageName, and unlike during frame
6502 // construction we already have an auto value from parentFrame, so we do
6503 // not use AutoFrameConstructionPageName here.
6504 state.mAutoPageNameValue = parentFrame->GetAutoPageValue();
6505#ifdef DEBUG1
6506 parentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
6507#endif
6508 }
6509
6510 LayoutFrameType frameType = parentFrame->Type();
6511
6512 RefPtr<ComputedStyle> parentStyle =
6513 ResolveComputedStyle(insertion.mContainer);
6514 FlattenedChildIterator iter(insertion.mContainer);
6515 const bool haveNoShadowDOM =
6516 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6517
6518 AutoFrameConstructionItemList items(this);
6519 if (aFirstNewContent->GetPreviousSibling() &&
6520 GetParentType(frameType) == eTypeBlock && haveNoShadowDOM) {
6521 // If there's a text node in the normal content list just before the new
6522 // items, and it has no frame, make a frame construction item for it. If it
6523 // doesn't need a frame, ConstructFramesFromItemList below won't give it
6524 // one. No need to do all this if our parent type is not block, though,
6525 // since WipeContainingBlock already handles that situation.
6526 //
6527 // Because we're appending, we don't need to worry about any text
6528 // after the appended content; there can only be generated content
6529 // (and bare text nodes are not generated). Native anonymous content
6530 // generated by frames never participates in inline layout.
6531 AddTextItemIfNeeded(state, *parentStyle, insertion,
6532 aFirstNewContent->GetPreviousSibling(), items);
6533 }
6534 for (nsIContent* child = aFirstNewContent; child;
6535 child = child->GetNextSibling()) {
6536 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
6537 items);
6538 }
6539
6540 nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling);
6541
6542 // Perform special check for diddling around with the frames in
6543 // a ib-split inline frame.
6544 // If we're appending before :after content, then we're not really
6545 // appending, so let WipeContainingBlock know that.
6546 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6547 if (WipeContainingBlock(state, containingBlock, parentFrame, items, true,
6548 prevSibling)) {
6549 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6550 return;
6551 }
6552 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6553
6554 // If the parent is a block frame, and we're not in a special case
6555 // where frames can be moved around, determine if the list is for the
6556 // start or end of the block.
6557 if (parentFrame->IsBlockFrameOrSubclass() && !haveFirstLetterStyle &&
6558 !haveFirstLineStyle && !IsFramePartOfIBSplit(parentFrame)) {
6559 items.SetLineBoundaryAtStart(!prevSibling ||
6560 !prevSibling->IsInlineOutside() ||
6561 prevSibling->IsBrFrame());
6562 // :after content can't be <br> so no need to check it
6563 //
6564 // FIXME(emilio): A display: contents sibling could! Write a test-case and
6565 // fix.
6566 items.SetLineBoundaryAtEnd(!nextSibling || !nextSibling->IsInlineOutside());
6567 }
6568 // To suppress whitespace-only text frames, we have to verify that
6569 // our container's DOM child list matches its flattened tree child list.
6570 items.SetParentHasNoShadowDOM(haveNoShadowDOM);
6571
6572 nsFrameConstructorSaveState floatSaveState;
6573 state.MaybePushFloatContainingBlock(parentFrame, floatSaveState);
6574
6575 nsFrameList frameList;
6576 ConstructFramesFromItemList(state, items, parentFrame,
6577 ParentIsWrapperAnonBox(parentFrame), frameList);
6578
6579 for (nsIContent* child = aFirstNewContent; child;
6580 child = child->GetNextSibling()) {
6581 // Invalidate now instead of before the WipeContainingBlock call, just in
6582 // case we do wipe; in that case we don't need to do this walk at all.
6583 // XXXbz does that matter? Would it make more sense to save some virtual
6584 // GetChildAt_Deprecated calls instead and do this during construction of
6585 // our FrameConstructionItemList?
6586 InvalidateCanvasIfNeeded(mPresShell, child);
6587 }
6588
6589 // If the container is a table and a caption was appended, it needs to be put
6590 // in the table wrapper frame's additional child list.
6591 nsFrameList captionList;
6592 if (LayoutFrameType::Table == frameType) {
6593 // Pull out the captions. Note that we don't want to do that as we go,
6594 // because processing a single caption can add a whole bunch of things to
6595 // the frame items due to pseudoframe processing. So we'd have to pull
6596 // captions from a list anyway; might as well do that here.
6597 // XXXbz this is no longer true; we could pull captions directly out of the
6598 // FrameConstructionItemList now.
6599 PullOutCaptionFrames(frameList, captionList);
6600 }
6601
6602 if (haveFirstLineStyle && parentFrame == containingBlock) {
6603 // It's possible that some of the new frames go into a
6604 // first-line frame. Look at them and see...
6605 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
6606 frameList);
6607 // That moved things into line frames as needed, reparenting their
6608 // styles. Nothing else needs to be done.
6609 } else if (parentFrame->Style()->HasPseudoElementData()) {
6610 // parentFrame might be inside a ::first-line frame. Check whether it is,
6611 // and if so fix up our styles.
6612 CheckForFirstLineInsertion(parentFrame, frameList);
6613 CheckForFirstLineInsertion(parentFrame, captionList);
6614 }
6615
6616 // Notify the parent frame passing it the list of new frames
6617 // Append the flowed frames to the principal child list; captions
6618 // need special treatment
6619 if (captionList.NotEmpty()) { // append the caption to the table wrapper
6620 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"
, 6620); MOZ_PretendNoReturn(); } } while (0)
;
6621 nsContainerFrame* outerTable = parentFrame->GetParent();
6622 captionList.ApplySetParent(outerTable);
6623 AppendFrames(outerTable, FrameChildListID::Caption, std::move(captionList));
6624 }
6625
6626 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6627 if (MaybeRecreateForColumnSpan(state, parentFrame, frameList, prevSibling)) {
6628 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6629 return;
6630 }
6631 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6632
6633 if (frameList.NotEmpty()) { // append the in-flow kids
6634 AppendFramesToParent(state, parentFrame, frameList, prevSibling);
6635 }
6636
6637 // Recover first-letter frames
6638 if (haveFirstLetterStyle) {
6639 RecoverLetterFrames(containingBlock);
6640 }
6641
6642#ifdef DEBUG1
6643 if (gReallyNoisyContentUpdates) {
6644 printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
6645 parentFrame->List(stdoutstdout);
6646 }
6647#endif
6648
6649#ifdef ACCESSIBILITY1
6650 if (nsAccessibilityService* accService = GetAccService()) {
6651 accService->ContentRangeInserted(mPresShell, aFirstNewContent, nullptr);
6652 }
6653#endif
6654}
6655
6656void nsCSSFrameConstructor::ContentInserted(nsIContent* aChild,
6657 InsertionKind aInsertionKind) {
6658 ContentRangeInserted(aChild, aChild->GetNextSibling(), aInsertionKind);
6659}
6660
6661// ContentRangeInserted handles creating frames for a range of nodes that
6662// aren't at the end of their childlist. ContentRangeInserted isn't a real
6663// content notification, but rather it handles regular ContentInserted calls
6664// for a single node as well as the lazy construction of frames for a range of
6665// nodes when called from CreateNeededFrames. For a range of nodes to be
6666// suitable to have its frames constructed all at once they must meet the same
6667// conditions that ContentAppended imposes (GetRangeInsertionPoint checks
6668// these), plus more. Namely when finding the insertion prevsibling we must not
6669// need to consult something specific to any one node in the range, so that the
6670// insertion prevsibling would be the same for each node in the range. So we
6671// pass the first node in the range to GetInsertionPrevSibling, and if
6672// IsValidSibling (the only place GetInsertionPrevSibling might look at the
6673// passed in node itself) needs to resolve style on the node we record this and
6674// return that this range needs to be split up and inserted separately. Table
6675// captions need extra attention as we need to determine where to insert them
6676// in the caption list, while skipping any nodes in the range being inserted
6677// (because when we treat the caption frames the other nodes have had their
6678// frames constructed but not yet inserted into the frame tree).
6679void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
6680 nsIContent* aEndChild,
6681 InsertionKind aInsertionKind) {
6682 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"
, 6683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6683; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6683 !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"
, 6683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6683; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6684
6685 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentRangeInserted",mozilla::AutoProfilerLabelHot raiiObject6686( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6686 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6686( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6687 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6688
6689 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"
, 6689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
") (" "must always pass a child" ")"); do { *((volatile int*
)__null) = 6689; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6690
6691#ifdef DEBUG1
6692 if (gNoisyContentUpdates) {
6693 printf(
6694 "nsCSSFrameConstructor::ContentRangeInserted container=%p "
6695 "start-child=%p end-child=%p lazy=%d\n",
6696 aStartChild->GetParent(), aStartChild, aEndChild,
6697 aInsertionKind == InsertionKind::Async);
6698 if (gReallyNoisyContentUpdates) {
6699 if (aStartChild->GetParent()) {
6700 aStartChild->GetParent()->List(stdoutstdout, 0);
6701 } else {
6702 aStartChild->List(stdoutstdout, 0);
6703 }
6704 }
6705 }
6706
6707 for (nsIContent* child = aStartChild; child != aEndChild;
6708 child = child->GetNextSibling()) {
6709 // XXX the GetContent() != child check is needed due to bug 135040.
6710 // Remove it once that's fixed.
6711 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"
, 6714); MOZ_PretendNoReturn(); } } while (0)
6712 !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"
, 6714); MOZ_PretendNoReturn(); } } while (0)
6713 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"
, 6714); MOZ_PretendNoReturn(); } } while (0)
6714 "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"
, 6714); MOZ_PretendNoReturn(); } } while (0)
;
6715 }
6716#endif
6717
6718 bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
6719 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"
, 6720); MOZ_PretendNoReturn(); } } while (0)
6720 "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"
, 6720); MOZ_PretendNoReturn(); } } while (0)
;
6721 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"
, 6722); MOZ_PretendNoReturn(); } } while (0)
6722 "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"
, 6722); MOZ_PretendNoReturn(); } } while (0)
;
6723
6724 // If we have a null parent, then this must be the document element being
6725 // inserted, or some other child of the document in the DOM (might be a PI,
6726 // say).
6727 if (!aStartChild->GetParent()) {
6728 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"
, 6729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6729 "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"
, 6729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6730 Element* docElement = mDocument->GetRootElement();
6731 if (aStartChild != docElement) {
6732 // Not the root element; just bail out
6733 return;
6734 }
6735
6736 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"
, 6736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "root element frame already created" ")"); do { *((volatile
int*)__null) = 6736; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6737 if (aInsertionKind == InsertionKind::Async) {
6738 docElement->SetFlags(NODE_NEEDS_FRAME);
6739 LazilyStyleNewChildRange(docElement, nullptr);
6740 return;
6741 }
6742
6743 // Create frames for the document element and its child elements
6744 if (ConstructDocElementFrame(docElement)) {
6745 InvalidateCanvasIfNeeded(mPresShell, aStartChild);
6746#ifdef DEBUG1
6747 if (gReallyNoisyContentUpdates) {
6748 printf(
6749 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
6750 "model:\n");
6751 mRootElementFrame->List(stdoutstdout);
6752 }
6753#endif
6754 }
6755
6756#ifdef ACCESSIBILITY1
6757 if (nsAccessibilityService* accService = GetAccService()) {
6758 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
6759 }
6760#endif
6761
6762 return;
6763 }
6764
6765 InsertionPoint insertion;
6766 if (isSingleInsert) {
6767 // See if we have a Shadow DOM insertion point. If so, then that's our real
6768 // parent frame; if not, then the frame hasn't been built yet and we just
6769 // bail.
6770 insertion = GetInsertionPoint(aStartChild);
6771 } else {
6772 // Get our insertion point. If we need to issue single ContentInserteds
6773 // GetRangeInsertionPoint will take care of that for us.
6774 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6775 insertion = GetRangeInsertionPoint(aStartChild, aEndChild, aInsertionKind);
6776 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6777 }
6778
6779 if (!insertion.mParentFrame) {
6780 // We're punting on frame construction because there's no container frame.
6781 // The Servo-backed style system handles this case like the lazy frame
6782 // construction case, except when we're already constructing frames, in
6783 // which case we shouldn't need to do anything else.
6784 if (aInsertionKind == InsertionKind::Async) {
6785 LazilyStyleNewChildRange(aStartChild, aEndChild);
6786 }
6787 return;
6788 }
6789
6790 if (aInsertionKind == InsertionKind::Async) {
6791 ConstructLazily(CONTENTINSERT, aStartChild);
6792 LazilyStyleNewChildRange(aStartChild, aEndChild);
6793 return;
6794 }
6795
6796 bool isAppend, isRangeInsertSafe;
6797 nsIFrame* prevSibling = GetInsertionPrevSibling(
6798 &insertion, aStartChild, &isAppend, &isRangeInsertSafe);
6799
6800 // check if range insert is safe
6801 if (!isSingleInsert && !isRangeInsertSafe) {
6802 // must fall back to a single ContertInserted for each child in the range
6803 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6804 IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
6805 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6806 return;
6807 }
6808
6809 LayoutFrameType frameType = insertion.mParentFrame->Type();
6810 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6811 if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild,
6812 aEndChild)) {
6813 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6814 return;
6815 }
6816 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6817
6818 // We should only get here with fieldsets when doing a single insert, because
6819 // fieldsets have multiple insertion points.
6820 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"
, 6821); MOZ_PretendNoReturn(); } } while (0)
6821 "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"
, 6821); MOZ_PretendNoReturn(); } } while (0)
;
6822 // Note that this check is insufficient if aStartChild is not a legend with
6823 // display::contents that contains a legend. We'll catch that case in
6824 // WipeContainingBlock. (That code would also catch this case, but handling
6825 // this early is slightly faster.)
6826 // XXXmats we should be able to optimize this when the fieldset doesn't
6827 // currently have a rendered legend. ContentRangeInserted needs to be fixed
6828 // to use the inner frame as the content insertion frame in that case.
6829 if (GetFieldSetFrameFor(insertion.mParentFrame) &&
6830 aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
6831 // Just reframe the parent, since figuring out whether this
6832 // should be the new legend and then handling it is too complex.
6833 // We could do a little better here --- check if the fieldset already
6834 // has a legend which occurs earlier in its child list than this node,
6835 // and if so, proceed. But we'd have to extend nsFieldSetFrame
6836 // to locate this legend in the inserted frames and extract it.
6837 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6838 RecreateFramesForContent(insertion.mParentFrame->GetContent(),
6839 InsertionKind::Async);
6840 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6841 return;
6842 }
6843
6844 // Don't construct kids of leaves
6845 if (insertion.mParentFrame->IsLeaf()) {
6846 // Clear lazy bits so we don't try to construct again.
6847 ClearLazyBits(aStartChild, aEndChild);
6848 return;
6849 }
6850
6851 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6852 if (WipeInsertionParent(insertion.mParentFrame)) {
6853 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6854 return;
6855 }
6856 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6857
6858 nsFrameConstructorState state(
6859 mPresShell, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
6860 GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
6861 GetFloatContainingBlock(insertion.mParentFrame),
6862 do_AddRef(mFrameTreeState));
6863
6864 // Recover state for the containing block - we need to know if
6865 // it has :first-letter or :first-line style applied to it. The
6866 // reason we care is that the internal structure in these cases
6867 // is not the normal structure and requires custom updating
6868 // logic.
6869 nsContainerFrame* containingBlock = state.mFloatedList.mContainingBlock;
6870 bool haveFirstLetterStyle = false;
6871 bool haveFirstLineStyle = false;
6872
6873 // In order to shave off some cycles, we only dig up the
6874 // containing block haveFirst* flags if the parent frame where
6875 // the insertion/append is occurring is an inline or block
6876 // container. For other types of containers this isn't relevant.
6877 StyleDisplayInside parentDisplayInside =
6878 insertion.mParentFrame->StyleDisplay()->DisplayInside();
6879
6880 // Examine the insertion.mParentFrame where the insertion is taking
6881 // place. If it's a certain kind of container then some special
6882 // processing is done.
6883 if (StyleDisplayInside::Flow == parentDisplayInside) {
6884 // Recover the special style flags for the containing block
6885 if (containingBlock) {
6886 haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
6887 haveFirstLineStyle = ShouldHaveFirstLineStyle(
6888 containingBlock->GetContent(), containingBlock->Style());
6889 }
6890
6891 if (haveFirstLetterStyle) {
6892 // If our current insertion.mParentFrame is a Letter frame, use its parent
6893 // as our new parent hint
6894 if (insertion.mParentFrame->IsLetterFrame()) {
6895 // If insertion.mParentFrame is out of flow, then we actually want the
6896 // parent of the placeholder frame.
6897 if (insertion.mParentFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
6898 nsPlaceholderFrame* placeholderFrame =
6899 insertion.mParentFrame->GetPlaceholderFrame();
6900 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"
, 6900); MOZ_PretendNoReturn(); } } while (0)
;
6901 insertion.mParentFrame = placeholderFrame->GetParent();
6902 } else {
6903 insertion.mParentFrame = insertion.mParentFrame->GetParent();
6904 }
6905 }
6906
6907 // Remove the old letter frames before doing the insertion
6908 RemoveLetterFrames(mPresShell, state.mFloatedList.mContainingBlock);
6909
6910 // Removing the letterframes messes around with the frame tree, removing
6911 // and creating frames. We need to reget our prevsibling, parent frame,
6912 // etc.
6913 prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend,
6914 &isRangeInsertSafe);
6915
6916 // Need check whether a range insert is still safe.
6917 if (!isSingleInsert && !isRangeInsertSafe) {
6918 // Need to recover the letter frames first.
6919 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
6920
6921 // must fall back to a single ContertInserted for each child in the
6922 // range
6923 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6924 IssueSingleInsertNofications(aStartChild, aEndChild,
6925 InsertionKind::Sync);
6926 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6927 return;
6928 }
6929
6930 frameType = insertion.mParentFrame->Type();
6931 }
6932 }
6933
6934 // This handles fallback to 'list-style-type' when a 'list-style-image' fails
6935 // to load.
6936 if (aStartChild->IsInNativeAnonymousSubtree() &&
6937 aStartChild->IsHTMLElement(nsGkAtoms::mozgeneratedcontentimage)) {
6938 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"
, 6938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
")"); do { *((volatile int*)__null) = 6938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6939 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"
, 6941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6941; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6940 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"
, 6941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6941; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6941 "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"
, 6941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6941; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6942 nsIContent* const nextSibling = aStartChild->GetNextSibling();
6943 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"
, 6944); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6944; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6944 "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"
, 6944); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6944; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6945 DestroyContext context(mPresShell);
6946 RemoveFrame(context, FrameChildListID::Principal,
6947 nextSibling->GetPrimaryFrame());
6948 auto* const container = aStartChild->GetParent()->AsElement();
6949 nsIContent* firstNewChild = nullptr;
6950 auto InsertChild = [this, container, nextSibling,
6951 &firstNewChild](RefPtr<nsIContent>&& aChild) {
6952 // We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
6953 // here; it would get set under AppendChildTo. But AppendChildTo might
6954 // think that we're going from not being anonymous to being anonymous and
6955 // do some extra work; setting the flag here avoids that.
6956 aChild->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
6957 container->InsertChildBefore(aChild, nextSibling, false, IgnoreErrors());
6958 if (auto* childElement = Element::FromNode(aChild)) {
6959 // If we created any children elements, Servo needs to traverse them,
6960 // but the root is already set up.
6961 mPresShell->StyleSet()->StyleNewSubtree(childElement);
6962 }
6963 if (!firstNewChild) {
6964 firstNewChild = aChild;
6965 }
6966 };
6967 CreateGeneratedContentFromListStyleType(
6968 state, *insertion.mContainer->AsElement(),
6969 *insertion.mParentFrame->Style(), InsertChild);
6970 if (!firstNewChild) {
6971 // No fallback content - we're done.
6972 return;
6973 }
6974 aStartChild = firstNewChild;
6975 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"
, 6976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6976; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6976 "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"
, 6976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6976; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6977 }
6978
6979 AutoFrameConstructionItemList items(this);
6980 RefPtr<ComputedStyle> parentStyle =
6981 ResolveComputedStyle(insertion.mContainer);
6982 ParentType parentType = GetParentType(frameType);
6983 FlattenedChildIterator iter(insertion.mContainer);
6984 const bool haveNoShadowDOM =
6985 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6986 if (aStartChild->GetPreviousSibling() && parentType == eTypeBlock &&
6987 haveNoShadowDOM) {
6988 // If there's a text node in the normal content list just before the
6989 // new nodes, and it has no frame, make a frame construction item for
6990 // it, because it might need a frame now. No need to do this if our
6991 // parent type is not block, though, since WipeContainingBlock
6992 // already handles that situation.
6993 AddTextItemIfNeeded(state, *parentStyle, insertion,
6994 aStartChild->GetPreviousSibling(), items);
6995 }
6996
6997 if (isSingleInsert) {
6998 AddFrameConstructionItems(state, aStartChild,
6999 aStartChild->IsRootOfNativeAnonymousSubtree(),
7000 *parentStyle, insertion, items);
7001 } else {
7002 for (nsIContent* child = aStartChild; child != aEndChild;
7003 child = child->GetNextSibling()) {
7004 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
7005 items);
7006 }
7007 }
7008
7009 if (aEndChild && parentType == eTypeBlock && haveNoShadowDOM) {
7010 // If there's a text node in the normal content list just after the
7011 // new nodes, and it has no frame, make a frame construction item for
7012 // it, because it might need a frame now. No need to do this if our
7013 // parent type is not block, though, since WipeContainingBlock
7014 // already handles that situation.
7015 AddTextItemIfNeeded(state, *parentStyle, insertion, aEndChild, items);
7016 }
7017
7018 // Perform special check for diddling around with the frames in
7019 // a special inline frame.
7020 // If we're appending before :after content, then we're not really
7021 // appending, so let WipeContainingBlock know that.
7022 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7023 if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items,
7024 isAppend, prevSibling)) {
7025 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7026 return;
7027 }
7028 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7029
7030 nsFrameConstructorSaveState floatSaveState;
7031 state.MaybePushFloatContainingBlock(insertion.mParentFrame, floatSaveState);
7032
7033 if (state.mPresContext->IsPaginated()) {
7034 // Because this function can be called outside frame construction, we need
7035 // to set state.mAutoPageNameValue based on what the parent frame's auto
7036 // value is.
7037 // Calling this from outside the frame constructor can violate many of the
7038 // expectations in AutoFrameConstructionPageName, and unlike during frame
7039 // construction we already have an auto value from parentFrame, so we do
7040 // not use AutoFrameConstructionPageName here.
7041 state.mAutoPageNameValue = insertion.mParentFrame->GetAutoPageValue();
7042#ifdef DEBUG1
7043 insertion.mParentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
7044#endif
7045 }
7046
7047 // If the container is a table and a caption will be appended, it needs to be
7048 // put in the table wrapper frame's additional child list.
7049 // We make no attempt here to set flags to indicate whether the list
7050 // will be at the start or end of a block. It doesn't seem worthwhile.
7051 nsFrameList frameList, captionList;
7052 ConstructFramesFromItemList(state, items, insertion.mParentFrame,
7053 ParentIsWrapperAnonBox(insertion.mParentFrame),
7054 frameList);
7055
7056 if (frameList.NotEmpty()) {
7057 for (nsIContent* child = aStartChild; child != aEndChild;
7058 child = child->GetNextSibling()) {
7059 InvalidateCanvasIfNeeded(mPresShell, child);
7060 }
7061
7062 if (LayoutFrameType::Table == frameType ||
7063 LayoutFrameType::TableWrapper == frameType) {
7064 PullOutCaptionFrames(frameList, captionList);
7065 if (prevSibling && prevSibling->IsTableCaption()) {
7066 // This can happen, but only if the table is empty (otherwise
7067 // SafeToInsertPseudoNeedingChildren bails).
7068 prevSibling = nullptr;
7069 }
7070 }
7071 }
7072
7073 if (haveFirstLineStyle && insertion.mParentFrame == containingBlock &&
7074 isAppend) {
7075 // It's possible that the new frame goes into a first-line
7076 // frame. Look at it and see...
7077 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
7078 frameList);
7079 } else if (insertion.mParentFrame->Style()->HasPseudoElementData()) {
7080 CheckForFirstLineInsertion(insertion.mParentFrame, frameList);
7081 CheckForFirstLineInsertion(insertion.mParentFrame, captionList);
7082 }
7083
7084 // We might have captions; put them into the caption list of the
7085 // table wrapper frame.
7086 if (captionList.NotEmpty()) {
7087 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"
, 7089); MOZ_PretendNoReturn(); } } while (0)
7088 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"
, 7089); MOZ_PretendNoReturn(); } } while (0)
7089 "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"
, 7089); MOZ_PretendNoReturn(); } } while (0)
;
7090 // We need to determine where to put the caption items; start with the
7091 // the parent frame that has already been determined and get the insertion
7092 // prevsibling of the first caption item.
7093 bool captionIsAppend;
7094 nsIFrame* captionPrevSibling = nullptr;
7095
7096 // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
7097 bool ignored;
7098 InsertionPoint captionInsertion = insertion;
7099 if (isSingleInsert) {
7100 captionPrevSibling = GetInsertionPrevSibling(
7101 &captionInsertion, aStartChild, &captionIsAppend, &ignored);
7102 } else {
7103 nsIContent* firstCaption = captionList.FirstChild()->GetContent();
7104 // It is very important here that we skip the children in
7105 // [aStartChild,aEndChild) when looking for a
7106 // prevsibling.
7107 captionPrevSibling = GetInsertionPrevSibling(
7108 &captionInsertion, firstCaption, &captionIsAppend, &ignored,
7109 aStartChild, aEndChild);
7110 }
7111
7112 nsContainerFrame* outerTable =
7113 captionInsertion.mParentFrame->IsTableFrame()
7114 ? captionInsertion.mParentFrame->GetParent()
7115 : captionInsertion.mParentFrame;
7116
7117 // If the parent is not a table wrapper frame we will try to add frames
7118 // to a named child list that the parent does not honor and the frames
7119 // will get lost.
7120 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"
, 7122); 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) = 7122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7121 "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"
, 7122); 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) = 7122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7122 "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"
, 7122); 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) = 7122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7123
7124 // If the parent of our current prevSibling is different from the frame
7125 // we'll actually use as the parent, then the calculated insertion
7126 // point is now invalid (bug 341382).
7127 if (captionPrevSibling && captionPrevSibling->GetParent() != outerTable) {
7128 captionPrevSibling = nullptr;
7129 }
7130
7131 captionList.ApplySetParent(outerTable);
7132 if (captionIsAppend) {
7133 AppendFrames(outerTable, FrameChildListID::Caption,
7134 std::move(captionList));
7135 } else {
7136 InsertFrames(outerTable, FrameChildListID::Caption, captionPrevSibling,
7137 std::move(captionList));
7138 }
7139 }
7140
7141 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7142 if (MaybeRecreateForColumnSpan(state, insertion.mParentFrame, frameList,
7143 prevSibling)) {
7144 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7145 return;
7146 }
7147 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7148
7149 if (frameList.NotEmpty()) {
7150 // Notify the parent frame
7151 if (isAppend) {
7152 AppendFramesToParent(state, insertion.mParentFrame, frameList,
7153 prevSibling);
7154 } else {
7155 InsertFrames(insertion.mParentFrame, FrameChildListID::Principal,
7156 prevSibling, std::move(frameList));
7157 }
7158 }
7159
7160 if (haveFirstLetterStyle) {
7161 // Recover the letter frames for the containing block when
7162 // it has first-letter style.
7163 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
7164 }
7165
7166#ifdef DEBUG1
7167 if (gReallyNoisyContentUpdates && insertion.mParentFrame) {
7168 printf(
7169 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
7170 "model:\n");
7171 insertion.mParentFrame->List(stdoutstdout);
7172 }
7173#endif
7174
7175#ifdef ACCESSIBILITY1
7176 if (nsAccessibilityService* accService = GetAccService()) {
7177 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
7178 }
7179#endif
7180}
7181
7182static bool IsWhitespaceFrame(const nsIFrame* aFrame) {
7183 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"
, 7183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 7183
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7184 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
7185}
7186
7187static bool IsSyntheticColGroup(const nsIFrame* aFrame) {
7188 return aFrame->IsTableColGroupFrame() &&
7189 static_cast<const nsTableColGroupFrame*>(aFrame)->IsSynthetic();
7190}
7191
7192static bool IsOnlyNonWhitespaceFrameInList(const nsFrameList& aFrameList,
7193 const nsIFrame* aFrame) {
7194 for (const nsIFrame* f : aFrameList) {
7195 if (f == aFrame) {
7196 // If we have continuations, ignore them too.
7197 aFrame = aFrame->GetNextContinuation();
7198 } else if (!IsWhitespaceFrame(f) && !IsSyntheticColGroup(f)) {
7199 // Synthetic colgroups get created unconditionally, so let's not consider
7200 // them as giving us a non-whitespace frame.
7201 return false;
7202 }
7203 }
7204 return true;
7205}
7206
7207static bool AllChildListsAreEffectivelyEmpty(nsIFrame* aFrame) {
7208 for (auto& [list, listID] : aFrame->ChildLists()) {
7209 if (list.IsEmpty()) {
7210 continue;
7211 }
7212 // We have some existing frame, usually that would be considered as making
7213 // this list nonempty. But let's make an exception for the synthetic
7214 // colgroup that tables have, since that gets created unconditionally.
7215 if (listID == FrameChildListID::ColGroup) {
7216 if (nsIFrame* f = list.OnlyChild(); f && IsSyntheticColGroup(f)) {
7217 continue;
7218 }
7219 }
7220 return false;
7221 }
7222 return true;
7223}
7224
7225static bool SafeToInsertPseudoNeedingChildren(nsIFrame* aFrame) {
7226 return AllChildListsAreEffectivelyEmpty(aFrame);
7227}
7228
7229// Returns true if aFrame is the only meaningful child of aParent (which is
7230// known to be a wrapper-pseudo). This lets us determine whether aParent can be
7231// removed, as a result of aFrame being removed.
7232static bool IsOnlyMeaningfulChildOfWrapperPseudo(nsIFrame* aFrame,
7233 nsIFrame* aParent) {
7234 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"
, 7234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsWrapperPseudo(aParent)"
")"); do { *((volatile int*)__null) = 7234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7235 // Handle a few special cases with tables and colgroups / captions.
7236 if (aParent->IsTableFrame()) {
7237 auto* wrapper = aParent->GetParent();
7238 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"
, 7238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper" ")"
); do { *((volatile int*)__null) = 7238; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7239 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"
, 7239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7239; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7240 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"
, 7241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7241; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7241 "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"
, 7241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7241; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7242 // We can't remove the table if there are any captions present (captions are
7243 // never anonymous themselves), because table wrapper always relies on
7244 // having a table frame.
7245 if (!wrapper->GetChildList(FrameChildListID::Caption).IsEmpty()) {
7246 return false;
7247 }
7248 // Similarly we can't remove the table if there's still a non-anonymous col
7249 // group (unless aFrame _is_ the non-anonymous colgroup).
7250 if (aFrame->IsTableColGroupFrame()) {
7251 return aParent->PrincipalChildList().IsEmpty() &&
7252 IsOnlyNonWhitespaceFrameInList(
7253 aParent->GetChildList(FrameChildListID::ColGroup), aFrame);
7254 }
7255 const auto& colGroupList =
7256 aParent->GetChildList(FrameChildListID::ColGroup);
7257 if (!colGroupList.IsEmpty()) {
7258 nsIFrame* f = colGroupList.OnlyChild();
7259 if (!f || !IsSyntheticColGroup(f)) {
7260 return false;
7261 }
7262 }
7263 }
7264 if (aFrame->IsTableCaption()) {
7265 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"
, 7265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7266 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"
, 7266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()"
")"); do { *((volatile int*)__null) = 7266; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7267 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"
, 7267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()->IsTableFrame()"
")"); do { *((volatile int*)__null) = 7267; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7268 return IsOnlyNonWhitespaceFrameInList(
7269 aParent->GetChildList(FrameChildListID::Caption), aFrame) &&
7270 // This checks for both colgroups and the principal list of the table
7271 // frame.
7272 AllChildListsAreEffectivelyEmpty(
7273 aParent->PrincipalChildList().OnlyChild());
7274 }
7275 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"
, 7275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableColGroupFrame()"
")"); do { *((volatile int*)__null) = 7275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7276 return IsOnlyNonWhitespaceFrameInList(aParent->PrincipalChildList(), aFrame);
7277}
7278
7279static bool CanRemoveWrapperPseudoForChildRemoval(nsIFrame* aFrame,
7280 nsIFrame* aParent) {
7281 if (!IsOnlyMeaningfulChildOfWrapperPseudo(aFrame, aParent)) {
7282 return false;
7283 }
7284 if (aParent->IsRubyBaseContainerFrame()) {
7285 // We can't remove the first ruby base container of a ruby frame unless
7286 // it has no siblings. See CreateNeededPseudoSiblings.
7287 return aParent->GetPrevSibling() || !aParent->GetNextSibling();
7288 }
7289 return true;
7290}
7291
7292bool nsCSSFrameConstructor::ContentRemoved(nsIContent* aChild,
7293 nsIContent* aOldNextSibling,
7294 RemoveFlags aFlags) {
7295 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"
, 7295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 7295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7296 MOZ_ASSERT(!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
" (" "Anonymous roots don't have siblings" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7297; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7297 "Anonymous roots don't have siblings")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
" (" "Anonymous roots don't have siblings" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7297; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7298 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentRemoved",mozilla::AutoProfilerLabelHot raiiObject7299( "nsCSSFrameConstructor::ContentRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7299 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7299( "nsCSSFrameConstructor::ContentRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7300 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7301 nsPresContext* presContext = mPresShell->GetPresContext();
7302 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"
, 7302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "presContext"
") (" "Our presShell should have a valid presContext" ")"); do
{ *((volatile int*)__null) = 7302; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7303
7304 // We want to detect when the viewport override element stored in the
7305 // prescontext is in the subtree being removed. Except in fullscreen cases
7306 // (which are handled in Element::UnbindFromTree and do not get stored on the
7307 // prescontext), the override element is always either the root element or a
7308 // <body> child of the root element. So we can only be removing the stored
7309 // override element if the thing being removed is either the override element
7310 // itself or the root element (which can be a parent of the override element).
7311 if (aChild == presContext->GetViewportScrollStylesOverrideElement() ||
7312 (aChild->IsElement() && !aChild->GetParent())) {
7313 // We might be removing the element that we propagated viewport scrollbar
7314 // styles from. Recompute those. (This clause covers two of the three
7315 // possible scrollbar-propagation sources: the <body> [as aChild or a
7316 // descendant] and the root node. The other possible scrollbar-propagation
7317 // source is a fullscreen element, and we have code elsewhere to update
7318 // scrollbars after fullscreen elements are removed -- specifically, it's
7319 // part of the fullscreen cleanup code called by Element::UnbindFromTree.
7320 // We don't handle the fullscreen case here, because it doesn't change the
7321 // scrollbar styles override element stored on the prescontext.)
7322 Element* newOverrideElement =
7323 presContext->UpdateViewportScrollStylesOverride();
7324
7325 // If aChild is the root, then we don't need to do any reframing of
7326 // newOverrideElement, because we're about to tear down the whole frame tree
7327 // anyway. And we need to make sure we don't do any such reframing, because
7328 // reframing the <body> can trigger a reframe of the <html> and then reenter
7329 // here.
7330 //
7331 // But if aChild is not the root, and if newOverrideElement is not
7332 // the root and isn't aChild (which it could be if all we're doing
7333 // here is reframing the current override element), it needs
7334 // reframing. In particular, it used to have a scrollframe
7335 // (because its overflow was not "visible"), but now it will
7336 // propagate its overflow to the viewport, so it should not need a
7337 // scrollframe anymore.
7338 if (aChild->GetParent() && newOverrideElement &&
7339 newOverrideElement->GetParent() && newOverrideElement != aChild) {
7340 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7341 RecreateFramesForContent(newOverrideElement, InsertionKind::Async);
7342 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7343 }
7344 }
7345
7346#ifdef DEBUG1
7347 if (gNoisyContentUpdates) {
7348 printf(
7349 "nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
7350 "old-next-sibling=%p\n",
7351 aChild->GetParent(), aChild, aOldNextSibling);
7352 if (gReallyNoisyContentUpdates) {
7353 aChild->GetParent()->List(stdoutstdout, 0);
7354 }
7355 }
7356#endif
7357
7358 nsIFrame* childFrame = aChild->GetPrimaryFrame();
7359 if (!childFrame || childFrame->GetContent() != aChild) {
7360 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7361 // Remove it once that's fixed.
7362 childFrame = nullptr;
7363 }
7364
7365 // If we're removing the root, then make sure to remove things starting at
7366 // the viewport's child instead of the primary frame (which might even be
7367 // null if the root was display:none, even though the frames above it got
7368 // created). Detecting removal of a root is a little exciting; in particular,
7369 // having no parent is necessary but NOT sufficient.
7370 //
7371 // Due to how we process reframes, the content node might not even be in our
7372 // document by now. So explicitly check whether the viewport's first kid's
7373 // content node is aChild.
7374 //
7375 // FIXME(emilio): I think the "might not be in our document" bit is impossible
7376 // now.
7377 bool isRoot = false;
7378 if (!aChild->GetParent()) {
7379 if (nsIFrame* viewport = GetRootFrame()) {
7380 nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
7381 if (firstChild && firstChild->GetContent() == aChild) {
7382 isRoot = true;
7383 childFrame = firstChild;
7384 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"
, 7384); MOZ_PretendNoReturn(); } } while (0)
;
7385 }
7386 }
7387 }
7388
7389 // We need to be conservative about when to determine whether something has
7390 // display: contents or not because at this point our actual display may be
7391 // different.
7392 //
7393 // Consider the case of:
7394 //
7395 // <div id="A" style="display: contents"><div id="B"></div></div>
7396 //
7397 // If we reconstruct A because its display changed to "none", we still need to
7398 // cleanup the frame on B, but A's display is now "none", so we can't poke at
7399 // the style of it.
7400 //
7401 // FIXME(emilio, bug 1450366): We can make this faster without adding much
7402 // complexity for the display: none -> other case, which right now
7403 // unnecessarily walks the content tree down.
7404 auto CouldHaveBeenDisplayContents = [aFlags](nsIContent* aContent) -> bool {
7405 return aFlags == REMOVE_FOR_RECONSTRUCTION || IsDisplayContents(aContent);
7406 };
7407
7408 if (!childFrame && CouldHaveBeenDisplayContents(aChild)) {
7409 // NOTE(emilio): We may iterate through ::before and ::after here and they
7410 // may be gone after the respective ContentRemoved call. Right now
7411 // StyleChildrenIterator handles that properly, so it's not an issue.
7412 StyleChildrenIterator iter(aChild);
7413 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
7414 if (c->GetPrimaryFrame() || CouldHaveBeenDisplayContents(c)) {
7415 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7416 bool didReconstruct = ContentRemoved(c, nullptr, aFlags);
7417 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7418 if (didReconstruct) {
7419 return true;
7420 }
7421 }
7422 }
7423 return false;
7424 }
7425
7426 if (childFrame) {
7427 if (aFlags == REMOVE_FOR_RECONSTRUCTION) {
7428 // Before removing the frames associated with the content object,
7429 // ask them to save their state onto our state object.
7430 CaptureStateForFramesOf(aChild, mFrameTreeState);
7431 }
7432
7433 InvalidateCanvasIfNeeded(mPresShell, aChild);
7434
7435 // See whether we need to remove more than just childFrame
7436 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7437 if (MaybeRecreateContainerForFrameRemoval(childFrame)) {
7438 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7439 return true;
7440 }
7441 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7442
7443 // Get the childFrame's parent frame
7444 nsIFrame* parentFrame = childFrame->GetParent();
7445 LayoutFrameType parentType = parentFrame->Type();
7446
7447 if (parentType == LayoutFrameType::FrameSet &&
7448 IsSpecialFramesetChild(aChild)) {
7449 // Just reframe the parent, since framesets are weird like that.
7450 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7451 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7452 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7453 return true;
7454 }
7455
7456 // If we're a child of MathML, then we should reframe the MathML content.
7457 // If we're non-MathML, then we would be wrapped in a block so we need to
7458 // check our grandparent in that case.
7459 nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
7460 ? parentFrame->GetParent()
7461 : parentFrame;
7462 if (possibleMathMLAncestor->IsMathMLFrame()) {
7463 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7464 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7465 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7466 return true;
7467 }
7468
7469#ifdef ACCESSIBILITY1
7470 if (aFlags != REMOVE_FOR_RECONSTRUCTION) {
7471 if (nsAccessibilityService* accService = GetAccService()) {
7472 accService->ContentRemoved(mPresShell, aChild);
7473 }
7474 }
7475#endif
7476
7477 // Examine the containing-block for the removed content and see if
7478 // :first-letter style applies.
7479 nsIFrame* inflowChild = childFrame;
7480 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7481 inflowChild = childFrame->GetPlaceholderFrame();
7482 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"
, 7482); MOZ_PretendNoReturn(); } } while (0)
;
7483 }
7484 nsContainerFrame* containingBlock =
7485 GetFloatContainingBlock(inflowChild->GetParent());
7486 bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
7487 if (haveFLS) {
7488 // Trap out to special routine that handles adjusting a blocks
7489 // frame tree when first-letter style is present.
7490#ifdef NOISY_FIRST_LETTER
7491 printf("ContentRemoved: containingBlock=");
7492 containingBlock->ListTag(stdoutstdout);
7493 printf(" parentFrame=");
7494 parentFrame->ListTag(stdoutstdout);
7495 printf(" childFrame=");
7496 childFrame->ListTag(stdoutstdout);
7497 printf("\n");
7498#endif
7499
7500 // First update the containing blocks structure by removing the
7501 // existing letter frames. This makes the subsequent logic
7502 // simpler.
7503 RemoveLetterFrames(mPresShell, containingBlock);
7504
7505 // Recover childFrame and parentFrame
7506 childFrame = aChild->GetPrimaryFrame();
7507 if (!childFrame || childFrame->GetContent() != aChild) {
7508 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7509 // Remove it once that's fixed.
7510 return false;
7511 }
7512 parentFrame = childFrame->GetParent();
7513 parentType = parentFrame->Type();
Value stored to 'parentType' is never read
7514
7515#ifdef NOISY_FIRST_LETTER
7516 printf(" ==> revised parentFrame=");
7517 parentFrame->ListTag(stdoutstdout);
7518 printf(" childFrame=");
7519 childFrame->ListTag(stdoutstdout);
7520 printf("\n");
7521#endif
7522 }
7523
7524#ifdef DEBUG1
7525 if (gReallyNoisyContentUpdates) {
7526 printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
7527 childFrame->ListTag(stdoutstdout);
7528 putchar('\n');
7529 parentFrame->List(stdoutstdout);
7530 }
7531#endif
7532
7533 // Notify the parent frame that it should delete the frame
7534 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7535 childFrame = childFrame->GetPlaceholderFrame();
7536 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"
, 7536); MOZ_PretendNoReturn(); } } while (0)
;
7537 parentFrame = childFrame->GetParent();
7538 }
7539
7540 // Take care of wrapper anonymous boxes that we might need to remove while
7541 // at it. Note that MaybeRecreateContainerForFrameRemoval takes care of
7542 // harder cases (merging sibling anonymous boxes etc).
7543 while (IsWrapperPseudo(parentFrame) &&
7544 CanRemoveWrapperPseudoForChildRemoval(childFrame, parentFrame)) {
7545 childFrame = parentFrame;
7546 parentFrame = childFrame->GetParent();
7547 }
7548
7549 DestroyContext context(mPresShell);
7550 RemoveFrame(context, nsLayoutUtils::GetChildListNameFor(childFrame),
7551 childFrame);
7552
7553 // NOTE(emilio): aChild could be dead here already if it is a ::before or
7554 // ::after pseudo-element (since in that case it was owned by childFrame,
7555 // which we just destroyed).
7556
7557 if (isRoot) {
7558 mRootElementFrame = nullptr;
7559 mRootElementStyleFrame = nullptr;
7560 mDocElementContainingBlock = nullptr;
7561 mCanvasFrame = nullptr;
7562 mPageSequenceFrame = nullptr;
7563 }
7564
7565 if (haveFLS && mRootElementFrame) {
7566 RecoverLetterFrames(containingBlock);
7567 }
7568
7569 // If we're just reconstructing frames for the element, then the
7570 // following ContentInserted notification on the element will
7571 // take care of fixing up any adjacent text nodes.
7572 if (aOldNextSibling && aFlags == REMOVE_CONTENT) {
7573 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"
, 7574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7574; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7574 "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"
, 7574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7574; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7575 // Adjacent whitespace-only text nodes might have been suppressed if
7576 // this node does not have inline ends. Create frames for them now
7577 // if necessary.
7578 // Reframe any text node just before the node being removed, if there is
7579 // one, and if it's not the last child or the first child. If a whitespace
7580 // textframe was being suppressed and it's now the last child or first
7581 // child then it can stay suppressed since the parent must be a block
7582 // and hence it's adjacent to a block end.
7583 // If aOldNextSibling is null, then the text node before the node being
7584 // removed is the last node, and we don't need to worry about it.
7585 nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
7586 if (prevSibling && prevSibling->GetPreviousSibling()) {
7587 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7588 ReframeTextIfNeeded(prevSibling);
7589 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7590 }
7591 // Reframe any text node just after the node being removed, if there is
7592 // one, and if it's not the last child or the first child.
7593 if (aOldNextSibling->GetNextSibling() &&
7594 aOldNextSibling->GetPreviousSibling()) {
7595 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7596 ReframeTextIfNeeded(aOldNextSibling);
7597 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7598 }
7599 }
7600
7601#ifdef DEBUG1
7602 if (gReallyNoisyContentUpdates && parentFrame) {
7603 printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
7604 parentFrame->List(stdoutstdout);
7605 }
7606#endif
7607 }
7608
7609 return false;
7610}
7611
7612/**
7613 * This method invalidates the canvas when frames are removed or added for a
7614 * node that might have its background propagated to the canvas, i.e., a
7615 * document root node or an HTML BODY which is a child of the root node.
7616 *
7617 * @param aFrame a frame for a content node about to be removed or a frame that
7618 * was just created for a content node that was inserted.
7619 */
7620static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode) {
7621 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"
, 7621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetRootFrame()"
") (" "What happened here?" ")"); do { *((volatile int*)__null
) = 7621; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
7622 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"
, 7622); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetPresContext()"
") (" "Say what?" ")"); do { *((volatile int*)__null) = 7622
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7623
7624 // Note that both in ContentRemoved and ContentInserted the content node
7625 // will still have the right parent pointer, so looking at that is ok.
7626
7627 nsIContent* parent = aNode->GetParent();
7628 if (parent) {
7629 // Has a parent; might not be what we want
7630 nsIContent* grandParent = parent->GetParent();
7631 if (grandParent) {
7632 // Has a grandparent, so not what we want
7633 return;
7634 }
7635
7636 // Check whether it's an HTML body
7637 if (!aNode->IsHTMLElement(nsGkAtoms::body)) {
7638 return;
7639 }
7640 }
7641
7642 // At this point the node has no parent or it's an HTML <body> child of the
7643 // root. We might not need to invalidate in this case (eg we might be in
7644 // XHTML or something), but chances are we want to. Play it safe.
7645 // Invalidate the viewport.
7646
7647 nsIFrame* rootFrame = aPresShell->GetRootFrame();
7648 rootFrame->InvalidateFrameSubtree();
7649}
7650
7651bool nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
7652 CharacterData* aContent) {
7653 if (!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
7654 return false;
7655 }
7656
7657 if (mAlwaysCreateFramesForIgnorableWhitespace) {
7658 return false;
7659 }
7660
7661 // Text frame may have been suppressed. Disable suppression and signal that a
7662 // flush should be performed. We do this on a document-wide basis so that
7663 // pages that repeatedly query metrics for collapsed-whitespace text nodes
7664 // don't trigger pathological behavior.
7665 mAlwaysCreateFramesForIgnorableWhitespace = true;
7666 Element* root = mDocument->GetRootElement();
7667 if (!root) {
7668 return false;
7669 }
7670
7671 RestyleManager()->PostRestyleEvent(root, RestyleHint{0},
7672 nsChangeHint_ReconstructFrame);
7673 return true;
7674}
7675
7676void nsCSSFrameConstructor::CharacterDataChanged(
7677 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) {
7678 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::CharacterDataChanged",mozilla::AutoProfilerLabelHot raiiObject7679( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7679 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7679( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7680 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7681
7682 if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
7683 !aContent->TextIsOnlyWhitespace()) ||
7684 (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
7685 aContent->TextIsOnlyWhitespace())) {
7686#ifdef DEBUG1
7687 nsIFrame* frame = aContent->GetPrimaryFrame();
7688 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"
, 7689); MOZ_PretendNoReturn(); } } while (0)
7689 "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"
, 7689); MOZ_PretendNoReturn(); } } while (0)
;
7690#endif
7691 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7692 RecreateFramesForContent(aContent, InsertionKind::Async);
7693 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7694 return;
7695 }
7696
7697 // It's possible the frame whose content changed isn't inserted into the
7698 // frame hierarchy yet, or that there is no frame that maps the content
7699 if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
7700#if 0
7701 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)
7702 ("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)
7703 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)
7704 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)
;
7705#endif
7706
7707 if (frame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) {
7708 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7709 RecreateFramesForContent(aContent, InsertionKind::Async);
7710 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7711 return;
7712 }
7713
7714 // Special check for text content that is a child of a letter frame. If
7715 // this happens, we should remove the letter frame, do whatever we're
7716 // planning to do with this notification, then put the letter frame back.
7717 // Note that this is basically what RecreateFramesForContent ends up doing;
7718 // the reason we dont' want to call that here is that our text content
7719 // could be native anonymous, in which case RecreateFramesForContent would
7720 // completely barf on it. And recreating the non-anonymous ancestor would
7721 // just lead us to come back into this notification (e.g. if quotes or
7722 // counters are involved), leading to a loop.
7723 nsContainerFrame* block = GetFloatContainingBlock(frame);
7724 bool haveFirstLetterStyle = false;
7725 if (block) {
7726 // See if the block has first-letter style applied to it.
7727 haveFirstLetterStyle = HasFirstLetterStyle(block);
7728 if (haveFirstLetterStyle) {
7729 RemoveLetterFrames(mPresShell, block);
7730 // Reget |frame|, since we might have killed it.
7731 // Do we really need to call CharacterDataChanged in this case, though?
7732 frame = aContent->GetPrimaryFrame();
7733 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"
, 7733); MOZ_PretendNoReturn(); } } while (0)
;
7734 }
7735 }
7736
7737 // Notify the first frame that maps the content. It will generate a reflow
7738 // command
7739 frame->CharacterDataChanged(aInfo);
7740
7741 if (haveFirstLetterStyle) {
7742 RecoverLetterFrames(block);
7743 }
7744 }
7745}
7746
7747void nsCSSFrameConstructor::RecalcQuotesAndCounters() {
7748 nsAutoScriptBlocker scriptBlocker;
7749
7750 if (mQuotesDirty) {
7751 mQuotesDirty = false;
7752 mContainStyleScopeManager.RecalcAllQuotes();
7753 }
7754
7755 if (mCountersDirty) {
7756 mCountersDirty = false;
7757 mContainStyleScopeManager.RecalcAllCounters();
7758 }
7759
7760 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"
, 7760); MOZ_PretendNoReturn(); } } while (0)
;
7761 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"
, 7761); MOZ_PretendNoReturn(); } } while (0)
;
7762}
7763
7764void nsCSSFrameConstructor::NotifyCounterStylesAreDirty() {
7765 mContainStyleScopeManager.SetAllCountersDirty();
7766 CountersDirty();
7767}
7768
7769void nsCSSFrameConstructor::WillDestroyFrameTree() {
7770#if defined(DEBUG_dbaron_off)
7771 mContainStyleScopeManager.DumpCounters();
7772#endif
7773
7774 // Prevent frame tree destruction from being O(N^2)
7775 mContainStyleScopeManager.Clear();
7776 nsFrameManager::Destroy();
7777}
7778
7779// STATIC
7780
7781// XXXbz I'd really like this method to go away. Once we have inline-block and
7782// I can just use that for sized broken images, that can happen, maybe.
7783//
7784// NOTE(emilio): This needs to match MozAltContent handling.
7785void nsCSSFrameConstructor::GetAlternateTextFor(const Element& aElement,
7786 nsAString& aAltText) {
7787 // The "alt" attribute specifies alternate text that is rendered
7788 // when the image can not be displayed.
7789 if (aElement.GetAttr(nsGkAtoms::alt, aAltText)) {
7790 return;
7791 }
7792
7793 if (aElement.IsHTMLElement(nsGkAtoms::input)) {
7794 // If there's no "alt" attribute, and aElement is an input element, then use
7795 // the value of the "value" attribute.
7796 if (aElement.GetAttr(nsGkAtoms::value, aAltText)) {
7797 return;
7798 }
7799
7800 // If there's no "value" attribute either, then use the localized string for
7801 // "Submit" as the alternate text.
7802 nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
7803 "Submit", aElement.OwnerDoc(),
7804 aAltText);
7805 }
7806}
7807
7808nsIFrame* nsCSSFrameConstructor::CreateContinuingOuterTableFrame(
7809 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7810 ComputedStyle* aComputedStyle) {
7811 nsTableWrapperFrame* newFrame =
7812 NS_NewTableWrapperFrame(mPresShell, aComputedStyle);
7813
7814 newFrame->Init(aContent, aParentFrame, aFrame);
7815
7816 // Create a continuing inner table frame, and if there's a caption then
7817 // replicate the caption
7818 nsFrameList newChildFrames;
7819
7820 nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
7821 if (childFrame) {
7822 nsIFrame* continuingTableFrame =
7823 CreateContinuingFrame(childFrame, newFrame);
7824 newChildFrames.AppendFrame(nullptr, continuingTableFrame);
7825
7826 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"
, 7827); MOZ_PretendNoReturn(); } } while (0)
7827 "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"
, 7827); MOZ_PretendNoReturn(); } } while (0)
;
7828 }
7829
7830 // Set the table wrapper's initial child list
7831 newFrame->SetInitialChildList(FrameChildListID::Principal,
7832 std::move(newChildFrames));
7833
7834 return newFrame;
7835}
7836
7837nsIFrame* nsCSSFrameConstructor::CreateContinuingTableFrame(
7838 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7839 ComputedStyle* aComputedStyle) {
7840 nsTableFrame* newFrame = NS_NewTableFrame(mPresShell, aComputedStyle);
7841
7842 newFrame->Init(aContent, aParentFrame, aFrame);
7843
7844 // Replicate any header/footer frames
7845 nsFrameList childFrames;
7846 for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
7847 // See if it's a header/footer, possibly wrapped in a scroll frame.
7848 nsTableRowGroupFrame* rowGroupFrame =
7849 static_cast<nsTableRowGroupFrame*>(childFrame);
7850 // If the row group was continued, then don't replicate it.
7851 nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
7852 if (rgNextInFlow) {
7853 rowGroupFrame->SetRepeatable(false);
7854 } else if (rowGroupFrame->IsRepeatable()) {
7855 // Replicate the header/footer frame.
7856 nsTableRowGroupFrame* headerFooterFrame;
7857 nsFrameList childList;
7858
7859 nsFrameConstructorState state(
7860 mPresShell, GetAbsoluteContainingBlock(newFrame, FIXED_POS),
7861 GetAbsoluteContainingBlock(newFrame, ABS_POS), nullptr);
7862 state.mCreatingExtraFrames = true;
7863
7864 ComputedStyle* const headerFooterComputedStyle = rowGroupFrame->Style();
7865 headerFooterFrame = static_cast<nsTableRowGroupFrame*>(
7866 NS_NewTableRowGroupFrame(mPresShell, headerFooterComputedStyle));
7867
7868 nsIContent* headerFooter = rowGroupFrame->GetContent();
7869 headerFooterFrame->Init(headerFooter, newFrame, nullptr);
7870
7871 nsFrameConstructorSaveState absoluteSaveState;
7872 MakeTablePartAbsoluteContainingBlock(state, absoluteSaveState,
7873 headerFooterFrame);
7874
7875 nsFrameConstructorSaveState floatSaveState;
7876 state.MaybePushFloatContainingBlock(headerFooterFrame, floatSaveState);
7877
7878 ProcessChildren(state, headerFooter, rowGroupFrame->Style(),
7879 headerFooterFrame, true, childList, false, nullptr);
7880 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"
, 7880); MOZ_PretendNoReturn(); } } while (0)
;
7881 headerFooterFrame->SetInitialChildList(FrameChildListID::Principal,
7882 std::move(childList));
7883 headerFooterFrame->SetRepeatable(true);
7884
7885 // Table specific initialization
7886 headerFooterFrame->InitRepeatedFrame(rowGroupFrame);
7887
7888 // XXX Deal with absolute and fixed frames...
7889 childFrames.AppendFrame(nullptr, headerFooterFrame);
7890 }
7891 }
7892
7893 // Set the table frame's initial child list
7894 newFrame->SetInitialChildList(FrameChildListID::Principal,
7895 std::move(childFrames));
7896
7897 return newFrame;
7898}
7899
7900nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
7901 nsIFrame* aFrame, nsContainerFrame* aParentFrame, bool aIsFluid) {
7902 ComputedStyle* computedStyle = aFrame->Style();
7903 nsIFrame* newFrame = nullptr;
7904 nsIFrame* nextContinuation = aFrame->GetNextContinuation();
7905 nsIFrame* nextInFlow = aFrame->GetNextInFlow();
7906
7907 // Use the frame type to determine what type of frame to create
7908 LayoutFrameType frameType = aFrame->Type();
7909 nsIContent* content = aFrame->GetContent();
7910
7911 if (LayoutFrameType::Text == frameType) {
7912 newFrame = NS_NewContinuingTextFrame(mPresShell, computedStyle);
7913 newFrame->Init(content, aParentFrame, aFrame);
7914 } else if (LayoutFrameType::Inline == frameType) {
7915 newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
7916 newFrame->Init(content, aParentFrame, aFrame);
7917 } else if (LayoutFrameType::Block == frameType) {
7918 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"
, 7919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7919; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7919 "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"
, 7919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7919; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7920 newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
7921 newFrame->Init(content, aParentFrame, aFrame);
7922 } else if (LayoutFrameType::ColumnSetWrapper == frameType) {
7923 newFrame =
7924 NS_NewColumnSetWrapperFrame(mPresShell, computedStyle, nsFrameState(0));
7925 newFrame->Init(content, aParentFrame, aFrame);
7926 } else if (LayoutFrameType::ColumnSet == frameType) {
7927 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"
, 7928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7928; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7928 "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"
, 7928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7928; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7929 newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
7930 newFrame->Init(content, aParentFrame, aFrame);
7931 } else if (LayoutFrameType::PrintedSheet == frameType) {
7932 newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
7933 } else if (LayoutFrameType::Page == frameType) {
7934 nsCanvasFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
7935 newFrame =
7936 ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
7937 } else if (LayoutFrameType::TableWrapper == frameType) {
7938 newFrame = CreateContinuingOuterTableFrame(aFrame, aParentFrame, content,
7939 computedStyle);
7940 } else if (LayoutFrameType::Table == frameType) {
7941 newFrame = CreateContinuingTableFrame(aFrame, aParentFrame, content,
7942 computedStyle);
7943 } else if (LayoutFrameType::TableRowGroup == frameType) {
7944 newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
7945 newFrame->Init(content, aParentFrame, aFrame);
7946 } else if (LayoutFrameType::TableRow == frameType) {
7947 nsTableRowFrame* rowFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
7948
7949 rowFrame->Init(content, aParentFrame, aFrame);
7950
7951 // Create a continuing frame for each table cell frame
7952 nsFrameList newChildList;
7953 nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
7954 while (cellFrame) {
7955 // See if it's a table cell frame
7956 if (cellFrame->IsTableCellFrame()) {
7957 nsIFrame* continuingCellFrame =
7958 CreateContinuingFrame(cellFrame, rowFrame);
7959 newChildList.AppendFrame(nullptr, continuingCellFrame);
7960 }
7961 cellFrame = cellFrame->GetNextSibling();
7962 }
7963
7964 rowFrame->SetInitialChildList(FrameChildListID::Principal,
7965 std::move(newChildList));
7966 newFrame = rowFrame;
7967
7968 } else if (LayoutFrameType::TableCell == frameType) {
7969 // Warning: If you change this and add a wrapper frame around table cell
7970 // frames, make sure Bug 368554 doesn't regress!
7971 // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
7972 nsTableFrame* tableFrame =
7973 static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
7974 nsTableCellFrame* cellFrame =
7975 NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
7976
7977 cellFrame->Init(content, aParentFrame, aFrame);
7978
7979 // Create a continuing area frame
7980 nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
7981 nsIFrame* continuingBlockFrame =
7982 CreateContinuingFrame(blockFrame, cellFrame);
7983
7984 SetInitialSingleChild(cellFrame, continuingBlockFrame);
7985 newFrame = cellFrame;
7986 } else if (LayoutFrameType::Line == frameType) {
7987 newFrame = NS_NewFirstLineFrame(mPresShell, computedStyle);
7988 newFrame->Init(content, aParentFrame, aFrame);
7989 } else if (LayoutFrameType::Letter == frameType) {
7990 newFrame = NS_NewFirstLetterFrame(mPresShell, computedStyle);
7991 newFrame->Init(content, aParentFrame, aFrame);
7992 } else if (LayoutFrameType::Image == frameType) {
7993 auto* imageFrame = static_cast<nsImageFrame*>(aFrame);
7994 newFrame = imageFrame->CreateContinuingFrame(mPresShell, computedStyle);
7995 newFrame->Init(content, aParentFrame, aFrame);
7996 } else if (LayoutFrameType::ImageControl == frameType) {
7997 newFrame = NS_NewImageControlFrame(mPresShell, computedStyle);
7998 newFrame->Init(content, aParentFrame, aFrame);
7999 } else if (LayoutFrameType::FieldSet == frameType) {
8000 newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
8001 newFrame->Init(content, aParentFrame, aFrame);
8002 } else if (LayoutFrameType::FlexContainer == frameType) {
8003 newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
8004 newFrame->Init(content, aParentFrame, aFrame);
8005 } else if (LayoutFrameType::GridContainer == frameType) {
8006 newFrame = NS_NewGridContainerFrame(mPresShell, computedStyle);
8007 newFrame->Init(content, aParentFrame, aFrame);
8008 } else if (LayoutFrameType::Ruby == frameType) {
8009 newFrame = NS_NewRubyFrame(mPresShell, computedStyle);
8010 newFrame->Init(content, aParentFrame, aFrame);
8011 } else if (LayoutFrameType::RubyBaseContainer == frameType) {
8012 newFrame = NS_NewRubyBaseContainerFrame(mPresShell, computedStyle);
8013 newFrame->Init(content, aParentFrame, aFrame);
8014 } else if (LayoutFrameType::RubyTextContainer == frameType) {
8015 newFrame = NS_NewRubyTextContainerFrame(mPresShell, computedStyle);
8016 newFrame->Init(content, aParentFrame, aFrame);
8017 } else {
8018 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"
, 8018); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected frame type"
")"); do { *((volatile int*)__null) = 8018; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
8019 }
8020
8021 // Init() set newFrame to be a fluid continuation of aFrame.
8022 // If we want a non-fluid continuation, we need to call SetPrevContinuation()
8023 // to reset NS_FRAME_IS_FLUID_CONTINUATION.
8024 if (!aIsFluid) {
8025 newFrame->SetPrevContinuation(aFrame);
8026 }
8027
8028 // If a continuing frame needs to carry frame state bits from its previous
8029 // continuation or parent, set them in nsIFrame::Init(), or in any derived
8030 // frame class's Init() if the bits are belong to specific group.
8031
8032 if (nextInFlow) {
8033 nextInFlow->SetPrevInFlow(newFrame);
8034 newFrame->SetNextInFlow(nextInFlow);
8035 } else if (nextContinuation) {
8036 nextContinuation->SetPrevContinuation(newFrame);
8037 newFrame->SetNextContinuation(nextContinuation);
8038 }
8039
8040 // aFrame cannot be a dynamic reflow root because it has a continuation now.
8041 aFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
8042
8043 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"
, 8043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newFrame->GetNextSibling()"
") (" "unexpected sibling" ")"); do { *((volatile int*)__null
) = 8043; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8044 return newFrame;
8045}
8046
8047void nsCSSFrameConstructor::MaybeSetNextPageContentFramePageName(
8048 const nsIFrame* aFrame) {
8049 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"
, 8049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Frame should not be null" ")"); do { *((volatile int*)__null
) = 8049; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8050 // No parent means the root frame, which isn't what this funciton is for.
8051 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"
, 8053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8053; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8052 "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"
, 8053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8053; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8053 "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"
, 8053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8053; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8054 if (mNextPageContentFramePageName) {
8055 return;
8056 }
8057 const nsAtom* const autoValue = aFrame->GetParent()->GetAutoPageValue();
8058 mNextPageContentFramePageName = aFrame->ComputePageValue(autoValue);
8059}
8060
8061nsresult nsCSSFrameConstructor::ReplicateFixedFrames(
8062 nsPageContentFrame* aParentFrame) {
8063 // Now deal with fixed-pos things.... They should appear on all pages,
8064 // so we want to move over the placeholders when processing the child
8065 // of the pageContentFrame.
8066
8067 nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
8068 if (!prevPageContentFrame) {
8069 return NS_OK;
8070 }
8071 nsContainerFrame* canvasFrame =
8072 do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
8073 nsIFrame* prevCanvasFrame =
8074 prevPageContentFrame->PrincipalChildList().FirstChild();
8075 if (!canvasFrame || !prevCanvasFrame) {
8076 // document's root element frame missing
8077 return NS_ERROR_UNEXPECTED;
8078 }
8079
8080 nsFrameList fixedPlaceholders;
8081 nsIFrame* firstFixed =
8082 prevPageContentFrame->GetChildList(FrameChildListID::Fixed).FirstChild();
8083 if (!firstFixed) {
8084 return NS_OK;
8085 }
8086
8087 // Don't allow abs-pos descendants of the fixed content to escape the content.
8088 // This should not normally be possible (because fixed-pos elements should
8089 // be absolute containers) but fixed-pos tables currently aren't abs-pos
8090 // containers.
8091 nsFrameConstructorState state(mPresShell, aParentFrame, nullptr,
8092 mRootElementFrame);
8093 state.mCreatingExtraFrames = true;
8094
8095 // We can't use an ancestor filter here, because we're not going to
8096 // be usefully recurring down the tree. This means that other
8097 // places in frame construction can't assume a filter is
8098 // initialized!
8099
8100 // Iterate across fixed frames and replicate each whose placeholder is a
8101 // descendant of aFrame. (We don't want to explicitly copy placeholders that
8102 // are within fixed frames, because that would cause duplicates on the new
8103 // page - bug 389619)
8104 for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
8105 nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame();
8106 if (prevPlaceholder && nsLayoutUtils::IsProperAncestorFrame(
8107 prevCanvasFrame, prevPlaceholder)) {
8108 // We want to use the same style as the primary style frame for
8109 // our content
8110 nsIContent* content = fixed->GetContent();
8111 ComputedStyle* computedStyle =
8112 nsLayoutUtils::GetStyleFrame(content)->Style();
8113 AutoFrameConstructionItemList items(this);
8114 AddFrameConstructionItemsInternal(state, content, canvasFrame, true,
8115 computedStyle,
8116 {ItemFlag::AllowPageBreak}, items);
8117 ConstructFramesFromItemList(state, items, canvasFrame,
8118 /* aParentIsWrapperAnonBox = */ false,
8119 fixedPlaceholders);
8120 }
8121 }
8122
8123 // Add the placeholders to our primary child list.
8124 // XXXbz this is a little screwed up, since the fixed frames will have
8125 // broken auto-positioning. Oh, well.
8126 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"
, 8127); MOZ_PretendNoReturn(); } } while (0)
8127 "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"
, 8127); MOZ_PretendNoReturn(); } } while (0)
;
8128 canvasFrame->SetInitialChildList(FrameChildListID::Principal,
8129 std::move(fixedPlaceholders));
8130 return NS_OK;
8131}
8132
8133nsCSSFrameConstructor::InsertionPoint nsCSSFrameConstructor::GetInsertionPoint(
8134 nsIContent* aChild) {
8135 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"
, 8135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 8135; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8136 nsIContent* insertionElement = aChild->GetFlattenedTreeParent();
8137 if (!insertionElement) {
8138 // The element doesn't belong in the flattened tree, and thus we don't want
8139 // to render it.
8140 return {};
8141 }
8142
8143 return {GetContentInsertionFrameFor(insertionElement), insertionElement};
8144}
8145
8146// Capture state for the frame tree rooted at the frame associated with the
8147// content object, aContent
8148void nsCSSFrameConstructor::CaptureStateForFramesOf(
8149 nsIContent* aContent, nsILayoutHistoryState* aHistoryState) {
8150 if (!aHistoryState) {
8151 return;
8152 }
8153 nsIFrame* frame = aContent->GetPrimaryFrame();
8154 if (frame == mRootElementFrame) {
8155 frame = mRootElementFrame
8156 ? GetAbsoluteContainingBlock(mRootElementFrame, FIXED_POS)
8157 : GetRootFrame();
8158 }
8159 for (; frame;
8160 frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
8161 CaptureFrameState(frame, aHistoryState);
8162 }
8163}
8164
8165static bool IsWhitespaceFrame(nsIFrame* aFrame) {
8166 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"
, 8166); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 8166
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8167 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
8168}
8169
8170static nsIFrame* FindNextNonWhitespaceSibling(nsIFrame* aFrame) {
8171 nsIFrame* f = aFrame;
8172 do {
8173 f = f->GetNextSibling();
8174 } while (f && IsWhitespaceFrame(f));
8175 return f;
8176}
8177
8178static nsIFrame* FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) {
8179 nsIFrame* f = aFrame;
8180 do {
8181 f = f->GetPrevSibling();
8182 } while (f && IsWhitespaceFrame(f));
8183 return f;
8184}
8185
8186bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
8187 nsIFrame* aFrame) {
8188#define TRACE(reason) \
8189 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)
8190 {}, 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)
8191 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"
, 8191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have a frame" ")"); do { *((volatile int*)__null) = 8191
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8192 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"
, 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame shouldn't be root" ")"); do { *((volatile int*)
__null) = 8192; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8193 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"
, 8194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8194; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8194 "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"
, 8194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8194; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8195
8196 nsIFrame* inFlowFrame = aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)
8197 ? aFrame->GetPlaceholderFrame()
8198 : aFrame;
8199 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"
, 8199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 8199; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8200 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"
, 8201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8201 "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"
, 8201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8202 nsIFrame* parent = inFlowFrame->GetParent();
8203
8204 if (inFlowFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
8205 nsIFrame* grandparent = parent->GetParent();
8206 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"
, 8206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "grandparent"
")"); do { *((volatile int*)__null) = 8206; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8207
8208 bool needsReframe =
8209 // 1. Removing a column-span may lead to an empty
8210 // ::-moz-column-span-wrapper.
8211 inFlowFrame->IsColumnSpan() ||
8212 // 2. Removing a frame which has any column-span siblings may also
8213 // lead to an empty ::-moz-column-span-wrapper subtree. The
8214 // column-span siblings were the frame's children, but later become
8215 // the frame's siblings after CreateColumnSpanSiblings().
8216 inFlowFrame->HasColumnSpanSiblings() ||
8217 // 3. Removing the only child of a ::-moz-column-content, whose
8218 // ColumnSet grandparent has a previous column-span sibling, requires
8219 // reframing since we might connect the ColumnSet's next column-span
8220 // sibling (if there's one). Note that this isn't actually needed if
8221 // the ColumnSet is at the end of ColumnSetWrapper since we create
8222 // empty ones at the end anyway, but we're not worried about
8223 // optimizing that case.
8224 (parent->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
8225 // The only child in ::-moz-column-content (might be tall enough to
8226 // split across columns)
8227 !inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8228 // That ::-moz-column-content is the first column.
8229 !parent->GetPrevInFlow() &&
8230 // The ColumnSet grandparent has a previous sibling that is a
8231 // column-span.
8232 grandparent->GetPrevSibling());
8233
8234 if (needsReframe) {
8235 nsContainerFrame* containingBlock =
8236 GetMultiColumnContainingBlockFor(inFlowFrame);
8237
8238#ifdef DEBUG1
8239 if (IsFramePartOfIBSplit(inFlowFrame)) {
8240 nsIFrame* ibContainingBlock = GetIBContainingBlockFor(inFlowFrame);
8241 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"
, 8245); 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) = 8245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8242 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"
, 8245); 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) = 8245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8243 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"
, 8245); 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) = 8245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8244 "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"
, 8245); 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) = 8245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8245 "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"
, 8245); 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) = 8245; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8246 }
8247#endif
8248
8249 TRACE("Multi-column");
8250 RecreateFramesForContent(containingBlock->GetContent(),
8251 InsertionKind::Async);
8252 return true;
8253 }
8254 }
8255
8256 if (IsFramePartOfIBSplit(aFrame)) {
8257 // The removal functions can't handle removal of an {ib} split directly; we
8258 // need to rebuild the containing block.
8259 TRACE("IB split removal");
8260 ReframeContainingBlock(aFrame);
8261 return true;
8262 }
8263
8264 if (inFlowFrame->IsRenderedLegend()) {
8265 TRACE("Fieldset / Legend");
8266 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8267 return true;
8268 }
8269
8270 // Might need to reconstruct things if this frame's nextSibling is a table
8271 // or ruby pseudo, since removal of this frame might mean that this pseudo
8272 // needs to get merged with the frame's prevSibling if that's also a table
8273 // or ruby pseudo.
8274 nsIFrame* nextSibling =
8275 FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
8276 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"
, 8277); MOZ_PretendNoReturn(); } } while (0)
8277 "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"
, 8277); MOZ_PretendNoReturn(); } } while (0)
;
8278 // Effectively, for the ruby pseudo sibling case, only pseudo <ruby> frame
8279 // need to be checked here, since all other types of such frames will have
8280 // a ruby container parent, and be catched by "Check ruby containers" below.
8281 if (nextSibling && IsWrapperPseudo(nextSibling)) {
8282 nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
8283 if (prevSibling && IsWrapperPseudo(prevSibling)) {
8284 TRACE("Pseudo sibling");
8285 // Good enough to recreate frames for aFrame's parent's content; even if
8286 // aFrame's parent is a pseudo, that'll be the right content node.
8287 // FIXME(emilio): Consider doing a more subtle check here like, only if
8288 // prevSibling and nextSibling share frame type. Or even consider just
8289 // moving the frames around and destroying nextSibling?
8290 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8291 return true;
8292 }
8293 }
8294
8295 // Check ruby containers
8296 LayoutFrameType parentType = parent->Type();
8297 if (parentType == LayoutFrameType::Ruby ||
8298 RubyUtils::IsRubyContainerBox(parentType)) {
8299 // In ruby containers, pseudo frames may be created from
8300 // whitespaces or even nothing. There are two cases we actually
8301 // need to handle here, but hard to check exactly:
8302 // 1. Status of spaces beside the frame may vary, and related
8303 // frames may be constructed or destroyed accordingly.
8304 // 2. The type of the first child of a ruby frame determines
8305 // whether a pseudo ruby base container should exist.
8306 TRACE("Ruby container");
8307 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8308 return true;
8309 }
8310
8311 // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
8312 // a non-fluid continuation, i.e. it was split by bidi resolution
8313 if (!inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8314 ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
8315 (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
8316 TRACE("Removing last child of non-fluid split parent");
8317 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8318 return true;
8319 }
8320
8321 // We might still need to reconstruct things if the parent of inFlowFrame is
8322 // ib-split, since in that case the removal of aFrame might affect the
8323 // splitting of its parent.
8324 if (!IsFramePartOfIBSplit(parent)) {
8325 return false;
8326 }
8327
8328 // If inFlowFrame is not the only in-flow child of |parent|, then removing
8329 // it will change nothing about the {ib} split.
8330 if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
8331 inFlowFrame->LastContinuation()->GetNextSibling()) {
8332 return false;
8333 }
8334
8335 // If the parent is the first or last part of the {ib} split, then
8336 // removing one of its kids will have no effect on the splitting.
8337 // Get the first continuation up front so we don't have to do it twice.
8338 nsIFrame* parentFirstContinuation = parent->FirstContinuation();
8339 if (!GetIBSplitSibling(parentFirstContinuation) ||
8340 !GetIBSplitPrevSibling(parentFirstContinuation)) {
8341 return false;
8342 }
8343
8344 TRACE("IB split parent");
8345 ReframeContainingBlock(parent);
8346 return true;
8347#undef TRACE
8348}
8349
8350void nsCSSFrameConstructor::UpdateTableCellSpans(nsIContent* aContent) {
8351 nsTableCellFrame* cellFrame = do_QueryFrame(aContent->GetPrimaryFrame());
8352
8353 // It's possible that this warning could fire if some other style change
8354 // simultaneously changes the 'display' of the element and makes it no
8355 // longer be a table cell.
8356 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"
, 8356); } } while (false)
;
8357
8358 if (cellFrame) {
8359 cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
8360 }
8361}
8362
8363static nsIContent* GetTopmostMathMLElement(nsIContent* aMathMLContent) {
8364 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"
, 8364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->IsMathMLElement()"
")"); do { *((volatile int*)__null) = 8364; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8365 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"
, 8365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()"
")"); do { *((volatile int*)__null) = 8365; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8366 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"
, 8366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()->IsMathMLFrame()"
")"); do { *((volatile int*)__null) = 8366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8367 nsIContent* root = aMathMLContent;
8368
8369 for (nsIContent* parent = aMathMLContent->GetFlattenedTreeParent(); parent;
8370 parent = parent->GetFlattenedTreeParent()) {
8371 nsIFrame* frame = parent->GetPrimaryFrame();
8372 if (!frame || !frame->IsMathMLFrame()) {
8373 break;
8374 }
8375 root = parent;
8376 }
8377
8378 return root;
8379}
8380
8381// We don't know how to re-insert an anonymous subtree root, so recreate the
8382// closest non-generated ancestor instead, except for a few special cases...
8383static bool ShouldRecreateContainerForNativeAnonymousContentRoot(
8384 nsIContent* aContent) {
8385 if (!aContent->IsRootOfNativeAnonymousSubtree()) {
8386 return false;
8387 }
8388 if (ManualNACPtr::IsManualNAC(aContent)) {
8389 // Editor NAC, would enter an infinite loop, and we sorta get away with it
8390 // because it's all abspos.
8391 return false;
8392 }
8393 if (auto* el = Element::FromNode(aContent)) {
8394 if (auto* classes = el->GetClasses()) {
8395 if (classes->Contains(nsGkAtoms::mozCustomContentContainer,
8396 eCaseMatters)) {
8397 // Canvas anonymous content (like the custom content container) is also
8398 // fine, because its only sibling is a tooltip which is also abspos, so
8399 // relative insertion order doesn't really matter.
8400 //
8401 // This is important because the inspector uses it, and we don't want
8402 // inspecting the page to change behavior heavily (and reframing
8403 // unfortunately has side-effects sometimes, even though they're bugs).
8404 return false;
8405 }
8406 }
8407 }
8408
8409 return true;
8410}
8411
8412void nsCSSFrameConstructor::RecreateFramesForContent(
8413 nsIContent* aContent, InsertionKind aInsertionKind) {
8414 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"
, 8414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 8414; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8415
8416 // If there is no document, we don't want to recreate frames for it. (You
8417 // shouldn't generally be giving this method content without a document
8418 // anyway).
8419 // Rebuilding the frame tree can have bad effects, especially if it's the
8420 // frame tree for chrome (see bug 157322).
8421 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"
, 8421)
) {
8422 return;
8423 }
8424
8425 // TODO(emilio): We technically can find the right insertion point nowadays
8426 // using StyleChildrenIterator rather than FlattenedChildIterator. But we'd
8427 // need to tweak the setup to insert into replaced elements to filter which
8428 // anonymous roots can be allowed, and which can't.
8429 //
8430 // TODO(emilio, 2022): Is this true? If we have a replaced element we wouldn't
8431 // have generated e.g., a ::before/::after pseudo-element to begin with (which
8432 // is what this code is about, so maybe we can just remove this piece of code
8433 // altogether).
8434 if (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent)) {
8435 do {
8436 aContent = aContent->GetParent();
8437 } while (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent));
8438 return RecreateFramesForContent(aContent, InsertionKind::Async);
8439 }
8440
8441 nsIFrame* frame = aContent->GetPrimaryFrame();
8442 if (frame && frame->IsMathMLFrame()) {
8443 // Reframe the topmost MathML element to prevent exponential blowup
8444 // (see bug 397518).
8445 aContent = GetTopmostMathMLElement(aContent);
8446 frame = aContent->GetPrimaryFrame();
8447 }
8448
8449 if (frame) {
8450 nsIFrame* parent = frame->GetParent();
8451 nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
8452 // If the parent frame is a leaf then the subsequent insert will fail to
8453 // create a frame, so we need to recreate the parent content. This happens
8454 // with native anonymous content from the editor.
8455 if (parent && parent->IsLeaf() && parentContent &&
8456 parentContent != aContent) {
8457 return RecreateFramesForContent(parentContent, InsertionKind::Async);
8458 }
8459 }
8460
8461 if (frame && MaybeRecreateContainerForFrameRemoval(frame)) {
8462 return;
8463 }
8464
8465 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"
, 8465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8466
8467 // Remove the frames associated with the content object.
8468 nsIContent* nextSibling = aContent->IsRootOfNativeAnonymousSubtree()
8469 ? nullptr
8470 : aContent->GetNextSibling();
8471 bool didReconstruct =
8472 ContentRemoved(aContent, nextSibling, REMOVE_FOR_RECONSTRUCTION);
8473
8474 if (!didReconstruct) {
8475 if (aInsertionKind == InsertionKind::Async && aContent->IsElement()) {
8476 // FIXME(emilio, bug 1397239): There's nothing removing the frame state
8477 // for elements that go away before we come back to the frame
8478 // constructor.
8479 //
8480 // Also, it'd be nice to just use the `ContentRangeInserted` path for
8481 // both elements and non-elements, but we need to make lazy frame
8482 // construction to apply to all elements first.
8483 RestyleManager()->PostRestyleEvent(aContent->AsElement(), RestyleHint{0},
8484 nsChangeHint_ReconstructFrame);
8485 } else {
8486 // Now, recreate the frames associated with this content object. If
8487 // ContentRemoved triggered reconstruction, then we don't need to do this
8488 // because the frames will already have been built.
8489 ContentRangeInserted(aContent, aContent->GetNextSibling(),
8490 aInsertionKind);
8491 }
8492 }
8493}
8494
8495bool nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent) {
8496 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"
, 8496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent && aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8496; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8497
8498 nsIContent* nextSibling = aContent->IsRootOfNativeAnonymousSubtree()
8499 ? nullptr
8500 : aContent->GetNextSibling();
8501
8502 return ContentRemoved(aContent, nextSibling, REMOVE_FOR_RECONSTRUCTION);
8503}
8504
8505//////////////////////////////////////////////////////////////////////
8506
8507// Block frame construction code
8508
8509already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
8510 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8511 if (aContent) {
8512 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8513 *aContent->AsElement(), PseudoStyleType::firstLetter, nullptr,
8514 aComputedStyle);
8515 }
8516 return nullptr;
8517}
8518
8519already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
8520 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8521 if (aContent) {
8522 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8523 *aContent->AsElement(), PseudoStyleType::firstLine, nullptr,
8524 aComputedStyle);
8525 }
8526 return nullptr;
8527}
8528
8529// Predicate to see if a given content (block element) has
8530// first-letter style applied to it.
8531bool nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(
8532 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8533 return nsLayoutUtils::HasPseudoStyle(aContent, aComputedStyle,
8534 PseudoStyleType::firstLetter,
8535 mPresShell->GetPresContext());
8536}
8537
8538bool nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame) {
8539 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"
, 8539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBlockFrame"
") (" "Need a frame" ")"); do { *((volatile int*)__null) = 8539
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8540 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"
, 8540); MOZ_PretendNoReturn(); } } while (0)
;
8541
8542 return aBlockFrame->HasAnyStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
8543}
8544
8545bool nsCSSFrameConstructor::ShouldHaveFirstLineStyle(
8546 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8547 bool hasFirstLine = nsLayoutUtils::HasPseudoStyle(
8548 aContent, aComputedStyle, PseudoStyleType::firstLine,
8549 mPresShell->GetPresContext());
8550 return hasFirstLine && !aContent->IsHTMLElement(nsGkAtoms::fieldset);
8551}
8552
8553void nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(
8554 nsIContent* aContent, ComputedStyle* aComputedStyle,
8555 bool* aHaveFirstLetterStyle, bool* aHaveFirstLineStyle) {
8556 *aHaveFirstLetterStyle = ShouldHaveFirstLetterStyle(aContent, aComputedStyle);
8557 *aHaveFirstLineStyle = ShouldHaveFirstLineStyle(aContent, aComputedStyle);
8558}
8559
8560/* static */
8561const nsCSSFrameConstructor::PseudoParentData
8562 nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
8563 // Cell
8564 {{&nsCSSFrameConstructor::ConstructTableCell,
8565 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8566 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8567 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28)},
8568 PseudoStyleType::tableCell},
8569 // Row
8570 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8571 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8572 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8573 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28)},
8574 PseudoStyleType::tableRow},
8575 // Row group
8576 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8577 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8578 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8579 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8580 PseudoStyleType::tableRowGroup},
8581 // Column group
8582 {{ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
8583 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 |
8584 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_USE_CHILD_ITEMS0x10000 |
8585 FCDATA_SKIP_ABSPOS_PUSH0x200 |
8586 // Not FCDATA_IS_WRAPPER_ANON_BOX, because we don't need to
8587 // restyle these: they have non-inheriting styles.
8588 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8589 PseudoStyleType::tableColGroup},
8590 // Table
8591 {{&nsCSSFrameConstructor::ConstructTable,
8592 FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8593 FCDATA_IS_WRAPPER_ANON_BOX0x400000},
8594 PseudoStyleType::table},
8595 // Ruby
8596 {{ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
,
8597 FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_USE_CHILD_ITEMS0x10000 |
8598 FCDATA_IS_WRAPPER_ANON_BOX0x400000 | FCDATA_SKIP_FRAMESET0x1},
8599 PseudoStyleType::ruby},
8600 // Ruby Base
8601 {{ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
8602 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8603 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8604 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28) |
8605 FCDATA_SKIP_FRAMESET0x1},
8606 PseudoStyleType::rubyBase},
8607 // Ruby Base Container
8608 {{ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
8609 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8610 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8611 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8612 FCDATA_SKIP_FRAMESET0x1},
8613 PseudoStyleType::rubyBaseContainer},
8614 // Ruby Text
8615 {{ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
8616 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8617 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8618 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28) |
8619 FCDATA_SKIP_FRAMESET0x1},
8620 PseudoStyleType::rubyText},
8621 // Ruby Text Container
8622 {{ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
8623 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8624 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8625 FCDATA_SKIP_FRAMESET0x1},
8626 PseudoStyleType::rubyTextContainer}};
8627
8628void nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
8629 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8630 nsIFrame* aParentFrame) {
8631 if (aItems.IsEmpty()) {
8632 return;
8633 }
8634
8635 if (!aParentFrame->IsFlexOrGridContainer()) {
8636 return;
8637 }
8638
8639 const bool isLegacyWebKitBox =
8640 IsFlexContainerForLegacyWebKitBox(aParentFrame);
8641 FCItemIterator iter(aItems);
8642 do {
8643 // Advance iter past children that don't want to be wrapped
8644 if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState,
8645 isLegacyWebKitBox)) {
8646 // Hit the end of the items without finding any remaining children that
8647 // need to be wrapped. We're finished!
8648 return;
8649 }
8650
8651 // If our next potentially-wrappable child is whitespace, then see if
8652 // there's anything wrappable immediately after it. If not, we just drop
8653 // the whitespace and move on. (We're not supposed to create any anonymous
8654 // flex/grid items that _only_ contain whitespace).
8655 // (BUT if this is generated content, then we don't give whitespace nodes
8656 // any special treatment, because they're probably not really whitespace --
8657 // they're just temporarily empty, waiting for their generated text.)
8658 // XXXdholbert If this node's generated text will *actually end up being
8659 // entirely whitespace*, then we technically should still skip over it, per
8660 // the CSS grid & flexbox specs. I'm not bothering with that at this point,
8661 // since it's a pretty extreme edge case.
8662 if (!aParentFrame->IsGeneratedContentFrame() &&
8663 iter.item().IsWhitespace(aState)) {
8664 FCItemIterator afterWhitespaceIter(iter);
8665 bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
8666 bool nextChildNeedsAnonItem =
8667 !hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(
8668 aState, isLegacyWebKitBox);
8669
8670 if (!nextChildNeedsAnonItem) {
8671 // There's nothing after the whitespace that we need to wrap, so we
8672 // just drop this run of whitespace.
8673 iter.DeleteItemsTo(this, afterWhitespaceIter);
8674 if (hitEnd) {
8675 // Nothing left to do -- we're finished!
8676 return;
8677 }
8678 // else, we have a next child and it does not want to be wrapped. So,
8679 // we jump back to the beginning of the loop to skip over that child
8680 // (and anything else non-wrappable after it)
8681 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"
, 8683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8683; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8682 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"
, 8683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8683; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8683 "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"
, 8683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8683; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8684 continue;
8685 }
8686 }
8687
8688 // Now |iter| points to the first child that needs to be wrapped in an
8689 // anonymous flex/grid item. Now we see how many children after it also want
8690 // to be wrapped in an anonymous flex/grid item.
8691 FCItemIterator endIter(iter); // iterator to find the end of the group
8692 endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox);
8693
8694 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"
, 8695); MOZ_PretendNoReturn(); } } while (0)
8695 "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"
, 8695); MOZ_PretendNoReturn(); } } while (0)
;
8696
8697 // Now, we create the anonymous flex or grid item to contain the children
8698 // between |iter| and |endIter|.
8699 nsIContent* parentContent = aParentFrame->GetContent();
8700 RefPtr<ComputedStyle> wrapperStyle =
8701 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
8702 PseudoStyleType::anonymousItem, aParentFrame->Style());
8703
8704 static constexpr FrameConstructionData sBlockFCData(
8705 ToCreationFunc(NS_NewBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewBlockFrame(aPs, aStyle); }
, FCDATA_SKIP_FRAMESET0x1 |
8706 FCDATA_USE_CHILD_ITEMS0x10000 |
8707 FCDATA_IS_WRAPPER_ANON_BOX0x400000);
8708
8709 // Use the content of our parent frame
8710 auto* newItem = new (this) FrameConstructionItem(
8711 &sBlockFCData, parentContent, wrapperStyle.forget(), true);
8712
8713 newItem->mIsAllInline =
8714 newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
8715 newItem->mIsBlock = !newItem->mIsAllInline;
8716
8717 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"
, 8720); 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) = 8720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8718 "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"
, 8720); 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) = 8720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8719 "(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"
, 8720); 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) = 8720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8720 "'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"
, 8720); 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) = 8720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8721
8722 // Anonymous flex and grid items induce line boundaries around their
8723 // contents.
8724 newItem->mChildItems.SetLineBoundaryAtStart(true);
8725 newItem->mChildItems.SetLineBoundaryAtEnd(true);
8726 // The parent of the items in aItems is also the parent of the items
8727 // in mChildItems
8728 newItem->mChildItems.SetParentHasNoShadowDOM(aItems.ParentHasNoShadowDOM());
8729
8730 // Eat up all items between |iter| and |endIter| and put them in our
8731 // wrapper. This advances |iter| to point to |endIter|.
8732 iter.AppendItemsToList(this, endIter, newItem->mChildItems);
8733
8734 iter.InsertItem(newItem);
8735 } while (!iter.IsDone());
8736}
8737
8738/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8739nsCSSFrameConstructor::ComputeRubyWhitespaceType(StyleDisplay aPrevDisplay,
8740 StyleDisplay aNextDisplay) {
8741 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"
, 8741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevDisplay.IsRuby() && aNextDisplay.IsRuby()"
")"); do { *((volatile int*)__null) = 8741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8742 if (aPrevDisplay == aNextDisplay &&
8743 (aPrevDisplay == StyleDisplay::RubyBase ||
8744 aPrevDisplay == StyleDisplay::RubyText)) {
8745 return eRubyInterLeafWhitespace;
8746 }
8747 if (aNextDisplay == StyleDisplay::RubyText ||
8748 aNextDisplay == StyleDisplay::RubyTextContainer) {
8749 return eRubyInterLevelWhitespace;
8750 }
8751 return eRubyInterSegmentWhitespace;
8752}
8753
8754/**
8755 * This function checks the content from |aStartIter| to |aEndIter|,
8756 * determines whether it contains only whitespace, and if yes,
8757 * interprets the type of whitespace. This method does not change
8758 * any of the iters.
8759 */
8760/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8761nsCSSFrameConstructor::InterpretRubyWhitespace(nsFrameConstructorState& aState,
8762 const FCItemIterator& aStartIter,
8763 const FCItemIterator& aEndIter) {
8764 if (!aStartIter.item().IsWhitespace(aState)) {
8765 return eRubyNotWhitespace;
8766 }
8767
8768 FCItemIterator spaceEndIter(aStartIter);
8769 spaceEndIter.SkipWhitespace(aState);
8770 if (spaceEndIter != aEndIter) {
8771 return eRubyNotWhitespace;
8772 }
8773
8774 // Any leading or trailing whitespace in non-pseudo ruby box
8775 // should have been trimmed, hence there should not be any
8776 // whitespace at the start or the end.
8777 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"
, 8777); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aStartIter.AtStart() && !aEndIter.IsDone()"
")"); do { *((volatile int*)__null) = 8777; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8778 FCItemIterator prevIter(aStartIter);
8779 prevIter.Prev();
8780 return ComputeRubyWhitespaceType(
8781 prevIter.item().mComputedStyle->StyleDisplay()->mDisplay,
8782 aEndIter.item().mComputedStyle->StyleDisplay()->mDisplay);
8783}
8784
8785/**
8786 * This function eats up consecutive items which do not want the current
8787 * parent into either a ruby base box or a ruby text box. When it
8788 * returns, |aIter| points to the first item it doesn't wrap.
8789 */
8790void nsCSSFrameConstructor::WrapItemsInPseudoRubyLeafBox(
8791 FCItemIterator& aIter, ComputedStyle* aParentStyle,
8792 nsIContent* aParentContent) {
8793 StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
8794 ParentType parentType, wrapperType;
8795 if (parentDisplay == StyleDisplay::RubyTextContainer) {
8796 parentType = eTypeRubyTextContainer;
8797 wrapperType = eTypeRubyText;
8798 } else {
8799 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"
, 8799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentDisplay == StyleDisplay::RubyBaseContainer"
")"); do { *((volatile int*)__null) = 8799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8800 parentType = eTypeRubyBaseContainer;
8801 wrapperType = eTypeRubyBase;
8802 }
8803
8804 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"
, 8805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8805; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8805 "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"
, 8805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8805; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8806
8807 FCItemIterator endIter(aIter);
8808 endIter.SkipItemsNotWantingParentType(parentType);
8809
8810 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8811 endIter);
8812}
8813
8814/**
8815 * This function eats up consecutive items into a ruby level container.
8816 * It may create zero or one level container. When it returns, |aIter|
8817 * points to the first item it doesn't wrap.
8818 */
8819void nsCSSFrameConstructor::WrapItemsInPseudoRubyLevelContainer(
8820 nsFrameConstructorState& aState, FCItemIterator& aIter,
8821 ComputedStyle* aParentStyle, nsIContent* aParentContent) {
8822 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"
, 8823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8823; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8823 "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"
, 8823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8823; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8824
8825 FrameConstructionItem& firstItem = aIter.item();
8826 ParentType wrapperType = firstItem.DesiredParentType();
8827 if (wrapperType != eTypeRubyTextContainer) {
8828 // If the first item is not ruby text,
8829 // it should be in a base container.
8830 wrapperType = eTypeRubyBaseContainer;
8831 }
8832
8833 FCItemIterator endIter(aIter);
8834 do {
8835 if (endIter.SkipItemsWantingParentType(wrapperType) ||
8836 // If the skipping above stops at some item which wants a
8837 // different ruby parent, then we have finished.
8838 IsRubyParentType(endIter.item().DesiredParentType())) {
8839 // No more items need to be wrapped in this level container.
8840 break;
8841 }
8842
8843 FCItemIterator contentEndIter(endIter);
8844 contentEndIter.SkipItemsNotWantingRubyParent();
8845 // endIter must be on something doesn't want a ruby parent.
8846 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"
, 8846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentEndIter != endIter"
")"); do { *((volatile int*)__null) = 8846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8847
8848 // InterpretRubyWhitespace depends on the fact that any leading or
8849 // trailing whitespace described in the spec have been trimmed at
8850 // this point. With this precondition, it is safe not to check
8851 // whether contentEndIter has been done.
8852 RubyWhitespaceType whitespaceType =
8853 InterpretRubyWhitespace(aState, endIter, contentEndIter);
8854 if (whitespaceType == eRubyInterLevelWhitespace) {
8855 // Remove inter-level whitespace.
8856 bool atStart = (aIter == endIter);
8857 endIter.DeleteItemsTo(this, contentEndIter);
8858 if (atStart) {
8859 aIter = endIter;
8860 }
8861 } else if (whitespaceType == eRubyInterSegmentWhitespace) {
8862 // If this level container starts with inter-segment whitespaces,
8863 // wrap them. Break at contentEndIter. Otherwise, leave it here.
8864 // Break at endIter. They will be wrapped when we are here again.
8865 if (aIter == endIter) {
8866 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"
, 8867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8867; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8867 "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"
, 8867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8867; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8868 endIter = contentEndIter;
8869 }
8870 break;
8871 } else if (wrapperType == eTypeRubyTextContainer &&
8872 whitespaceType != eRubyInterLeafWhitespace) {
8873 // Misparented inline content that's not inter-annotation
8874 // whitespace doesn't belong in a pseudo ruby text container.
8875 // Break at endIter.
8876 break;
8877 } else {
8878 endIter = contentEndIter;
8879 }
8880 } while (!endIter.IsDone());
8881
8882 // It is possible that everything our parent wants us to wrap is
8883 // simply an inter-level whitespace, which has been trimmed, or
8884 // an inter-segment whitespace, which will be wrapped later.
8885 // In those cases, don't create anything.
8886 if (aIter != endIter) {
8887 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8888 endIter);
8889 }
8890}
8891
8892/**
8893 * This function trims leading and trailing whitespaces
8894 * in the given item list.
8895 */
8896void nsCSSFrameConstructor::TrimLeadingAndTrailingWhitespaces(
8897 nsFrameConstructorState& aState, FrameConstructionItemList& aItems) {
8898 FCItemIterator iter(aItems);
8899 if (!iter.IsDone() && iter.item().IsWhitespace(aState)) {
8900 FCItemIterator spaceEndIter(iter);
8901 spaceEndIter.SkipWhitespace(aState);
8902 iter.DeleteItemsTo(this, spaceEndIter);
8903 }
8904
8905 iter.SetToEnd();
8906 if (!iter.AtStart()) {
8907 FCItemIterator spaceEndIter(iter);
8908 do {
8909 iter.Prev();
8910 if (iter.AtStart()) {
8911 // It's fine to not check the first item, because we
8912 // should have trimmed leading whitespaces above.
8913 break;
8914 }
8915 } while (iter.item().IsWhitespace(aState));
8916 iter.Next();
8917 if (iter != spaceEndIter) {
8918 iter.DeleteItemsTo(this, spaceEndIter);
8919 }
8920 }
8921}
8922
8923/**
8924 * This function walks through the child list (aItems) and creates
8925 * needed pseudo ruby boxes to wrap misparented children.
8926 */
8927void nsCSSFrameConstructor::CreateNeededPseudoInternalRubyBoxes(
8928 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8929 nsIFrame* aParentFrame) {
8930 const ParentType ourParentType = GetParentType(aParentFrame);
8931 if (!IsRubyParentType(ourParentType) ||
8932 aItems.AllWantParentType(ourParentType)) {
8933 return;
8934 }
8935
8936 if (!IsRubyPseudo(aParentFrame) ||
8937 ourParentType == eTypeRuby /* for 'display:block ruby' */) {
8938 // Normally, ruby pseudo frames start from and end at some elements,
8939 // which means they don't have leading and trailing whitespaces at
8940 // all. But there are two cases where they do actually have leading
8941 // or trailing whitespaces:
8942 // 1. It is an inter-segment whitespace which in an individual ruby
8943 // base container.
8944 // 2. The pseudo frame starts from or ends at consecutive inline
8945 // content, which is not pure whitespace, but includes some.
8946 // In either case, the whitespaces are not the leading or trailing
8947 // whitespaces defined in the spec, and thus should not be trimmed.
8948 TrimLeadingAndTrailingWhitespaces(aState, aItems);
8949 }
8950
8951 FCItemIterator iter(aItems);
8952 nsIContent* parentContent = aParentFrame->GetContent();
8953 ComputedStyle* parentStyle = aParentFrame->Style();
8954 while (!iter.IsDone()) {
8955 if (!iter.SkipItemsWantingParentType(ourParentType)) {
8956 if (ourParentType == eTypeRuby) {
8957 WrapItemsInPseudoRubyLevelContainer(aState, iter, parentStyle,
8958 parentContent);
8959 } else {
8960 WrapItemsInPseudoRubyLeafBox(iter, parentStyle, parentContent);
8961 }
8962 }
8963 }
8964}
8965
8966/*
8967 * This function works as follows: we walk through the child list (aItems) and
8968 * find items that cannot have aParentFrame as their parent. We wrap
8969 * continuous runs of such items into a FrameConstructionItem for a frame that
8970 * gets them closer to their desired parents. For example, a run of non-row
8971 * children of a row-group will get wrapped in a row. When we later construct
8972 * the frame for this wrapper (in this case for the row), it'll be the correct
8973 * parent for the cells in the set of items we wrapped or we'll wrap cells
8974 * around everything else. At the end of this method, aItems is guaranteed to
8975 * contain only items for frames that can be direct kids of aParentFrame.
8976 */
8977void nsCSSFrameConstructor::CreateNeededPseudoContainers(
8978 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8979 nsIFrame* aParentFrame) {
8980 ParentType ourParentType = GetParentType(aParentFrame);
8981 if (IsRubyParentType(ourParentType) ||
8982 aItems.AllWantParentType(ourParentType)) {
8983 // Nothing to do here
8984 return;
8985 }
8986
8987 FCItemIterator iter(aItems);
8988 do {
8989 if (iter.SkipItemsWantingParentType(ourParentType)) {
8990 // Nothing else to do here; we're finished
8991 return;
8992 }
8993
8994 // Now we're pointing to the first child that wants a different parent
8995 // type.
8996
8997 // Now try to figure out what kids we can group together. We can generally
8998 // group everything that has a different desired parent type from us. Two
8999 // exceptions to this:
9000 // 1) If our parent type is table, we can't group columns with anything
9001 // else other than whitespace.
9002 // 2) Whitespace that lies between two things we can group which both want
9003 // a non-block parent should be dropped, even if we can't group them
9004 // with each other and even if the whitespace wants a parent of
9005 // ourParentType. Ends of the list count as things that don't want a
9006 // block parent (so that for example we'll drop a whitespace-only list).
9007
9008 FCItemIterator endIter(iter); /* iterator to find the end of the group */
9009 ParentType groupingParentType = endIter.item().DesiredParentType();
9010 if (aItems.AllWantParentType(groupingParentType) &&
9011 groupingParentType != eTypeBlock) {
9012 // Just group them all and be done with it. We need the check for
9013 // eTypeBlock here to catch the "all the items are whitespace" case
9014 // described above.
9015 endIter.SetToEnd();
9016 } else {
9017 // Locate the end of the group.
9018
9019 // Keep track of the type the previous item wanted, in case we have to
9020 // deal with whitespace. Start it off with ourParentType, since that's
9021 // the last thing |iter| would have skipped over.
9022 ParentType prevParentType = ourParentType;
9023 do {
9024 // Walk an iterator past any whitespace that we might be able to drop
9025 // from the list
9026 FCItemIterator spaceEndIter(endIter);
9027 if (prevParentType != eTypeBlock &&
9028 !aParentFrame->IsGeneratedContentFrame() &&
9029 spaceEndIter.item().IsWhitespace(aState)) {
9030 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
9031
9032 // We drop the whitespace in the following cases:
9033 // 1) If these are not trailing spaces and the next item wants a table
9034 // or table-part parent
9035 // 2) If these are trailing spaces and aParentFrame is a
9036 // tabular container according to rule 1.3 of CSS 2.1 Sec 17.2.1.
9037 // (Being a tabular container pretty much means ourParentType is
9038 // not eTypeBlock besides the eTypeColGroup case, which won't
9039 // reach here.)
9040 if ((!trailingSpaces &&
9041 IsTableParentType(spaceEndIter.item().DesiredParentType())) ||
9042 (trailingSpaces && ourParentType != eTypeBlock)) {
9043 bool updateStart = (iter == endIter);
9044 endIter.DeleteItemsTo(this, spaceEndIter);
9045 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"
, 9046); MOZ_PretendNoReturn(); } } while (0)
9046 "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"
, 9046); MOZ_PretendNoReturn(); } } while (0)
;
9047
9048 if (updateStart) {
9049 iter = endIter;
9050 }
9051
9052 if (trailingSpaces) {
9053 break; /* Found group end */
9054 }
9055
9056 if (updateStart) {
9057 // Update groupingParentType, since it might have been eTypeBlock
9058 // just because of the whitespace.
9059 groupingParentType = iter.item().DesiredParentType();
9060 }
9061 }
9062 }
9063
9064 // Now endIter points to a non-whitespace item or a non-droppable
9065 // whitespace item. In the latter case, if this is the end of the group
9066 // we'll traverse this whitespace again. But it'll all just be quick
9067 // DesiredParentType() checks which will match ourParentType (that's
9068 // what it means that this is the group end), so it's OK.
9069 // However, when we are grouping a ruby parent, and endIter points to
9070 // a non-droppable whitespace, if the next non-whitespace item also
9071 // wants a ruby parent, the whitespace should also be included into
9072 // the current ruby container.
9073 prevParentType = endIter.item().DesiredParentType();
9074 if (prevParentType == ourParentType &&
9075 (endIter == spaceEndIter || spaceEndIter.IsDone() ||
9076 !IsRubyParentType(groupingParentType) ||
9077 !IsRubyParentType(spaceEndIter.item().DesiredParentType()))) {
9078 // End the group at endIter.
9079 break;
9080 }
9081
9082 if (ourParentType == eTypeTable &&
9083 (prevParentType == eTypeColGroup) !=
9084 (groupingParentType == eTypeColGroup)) {
9085 // Either we started with columns and now found something else, or
9086 // vice versa. In any case, end the grouping.
9087 break;
9088 }
9089
9090 // If we have some whitespace that we were not able to drop and there is
9091 // an item after the whitespace that is already properly parented, then
9092 // make sure to include the spaces in our group but stop the group after
9093 // that.
9094 if (spaceEndIter != endIter && !spaceEndIter.IsDone() &&
9095 ourParentType == spaceEndIter.item().DesiredParentType()) {
9096 endIter = spaceEndIter;
9097 break;
9098 }
9099
9100 // Include the whitespace we didn't drop (if any) in the group.
9101 endIter = spaceEndIter;
9102 prevParentType = endIter.item().DesiredParentType();
9103
9104 endIter.Next();
9105 } while (!endIter.IsDone());
9106 }
9107
9108 if (iter == endIter) {
9109 // Nothing to wrap here; just skipped some whitespace
9110 continue;
9111 }
9112
9113 // Now group together all the items between iter and endIter. The right
9114 // parent type to use depends on ourParentType.
9115 ParentType wrapperType;
9116 switch (ourParentType) {
9117 case eTypeRow:
9118 // The parent type for a cell is eTypeBlock, since that's what a cell
9119 // looks like to its kids.
9120 wrapperType = eTypeBlock;
9121 break;
9122 case eTypeRowGroup:
9123 wrapperType = eTypeRow;
9124 break;
9125 case eTypeTable:
9126 // Either colgroup or rowgroup, depending on what we're grouping.
9127 wrapperType =
9128 groupingParentType == eTypeColGroup ? eTypeColGroup : eTypeRowGroup;
9129 break;
9130 case eTypeColGroup:
9131 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"
, 9131); AnnotateMozCrashReason("MOZ_CRASH(" "Colgroups should be suppresing non-col child items"
")"); do { *((volatile int*)__null) = 9131; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9132 default:
9133 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"
, 9133); MOZ_PretendNoReturn(); } } while (0)
;
9134 if (IsRubyParentType(groupingParentType)) {
9135 wrapperType = eTypeRuby;
9136 } else {
9137 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"
, 9138); MOZ_PretendNoReturn(); } } while (0)
9138 "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"
, 9138); MOZ_PretendNoReturn(); } } while (0)
;
9139 wrapperType = eTypeTable;
9140 }
9141 }
9142
9143 ComputedStyle* parentStyle = aParentFrame->Style();
9144 WrapItemsInPseudoParent(aParentFrame->GetContent(), parentStyle,
9145 wrapperType, iter, endIter);
9146
9147 // Now |iter| points to the item that was the first one we didn't wrap;
9148 // loop and see whether we need to skip it or wrap it in something
9149 // different.
9150 } while (!iter.IsDone());
9151}
9152
9153/**
9154 * This method wraps frame construction item from |aIter| to
9155 * |aEndIter|. After it returns, aIter points to the first item
9156 * after the wrapper.
9157 */
9158void nsCSSFrameConstructor::WrapItemsInPseudoParent(
9159 nsIContent* aParentContent, ComputedStyle* aParentStyle,
9160 ParentType aWrapperType, FCItemIterator& aIter,
9161 const FCItemIterator& aEndIter) {
9162 const PseudoParentData& pseudoData = sPseudoParentData[aWrapperType];
9163 PseudoStyleType pseudoType = pseudoData.mPseudoType;
9164 auto& parentDisplay = *aParentStyle->StyleDisplay();
9165 auto parentDisplayInside = parentDisplay.DisplayInside();
9166
9167 // XXXmats should we use IsInlineInsideStyle() here instead? seems odd to
9168 // exclude RubyBaseContainer/RubyTextContainer...
9169 if (pseudoType == PseudoStyleType::table &&
9170 (parentDisplay.IsInlineFlow() ||
9171 parentDisplayInside == StyleDisplayInside::RubyBase ||
9172 parentDisplayInside == StyleDisplayInside::RubyText)) {
9173 pseudoType = PseudoStyleType::inlineTable;
9174 }
9175
9176 RefPtr<ComputedStyle> wrapperStyle;
9177 if (pseudoData.mFCData.mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000) {
9178 wrapperStyle = mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9179 pseudoType, aParentStyle);
9180 } else {
9181 wrapperStyle =
9182 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
9183 pseudoType);
9184 }
9185
9186 // Use the content of our parent frame
9187 auto* newItem = new (this) FrameConstructionItem(
9188 &pseudoData.mFCData, aParentContent, wrapperStyle.forget(), true);
9189
9190 const nsStyleDisplay* disp = newItem->mComputedStyle->StyleDisplay();
9191 // Here we're cheating a tad... technically, table-internal items should be
9192 // inline if aParentFrame is inline, but they'll get wrapped in an
9193 // inline-table in the end, so it'll all work out. In any case, arguably
9194 // we don't need to maintain this state at this point... but it's better
9195 // to, I guess.
9196 newItem->mIsAllInline = disp->IsInlineOutsideStyle();
9197
9198 bool isRuby = disp->IsRubyDisplayType();
9199 if (!isRuby) {
9200 // Table pseudo frames always induce line boundaries around their
9201 // contents.
9202 newItem->mChildItems.SetLineBoundaryAtStart(true);
9203 newItem->mChildItems.SetLineBoundaryAtEnd(true);
9204 }
9205 // The parent of the items in aItems is also the parent of the items
9206 // in mChildItems
9207 newItem->mChildItems.SetParentHasNoShadowDOM(
9208 aIter.List()->ParentHasNoShadowDOM());
9209
9210 // Eat up all items between |aIter| and |aEndIter| and put them in our
9211 // wrapper Advances |aIter| to point to |aEndIter|.
9212 aIter.AppendItemsToList(this, aEndIter, newItem->mChildItems);
9213
9214 aIter.InsertItem(newItem);
9215}
9216
9217void nsCSSFrameConstructor::CreateNeededPseudoSiblings(
9218 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9219 nsIFrame* aParentFrame) {
9220 if (aItems.IsEmpty() || GetParentType(aParentFrame) != eTypeRuby) {
9221 return;
9222 }
9223
9224 FCItemIterator iter(aItems);
9225 StyleDisplay firstDisplay =
9226 iter.item().mComputedStyle->StyleDisplay()->mDisplay;
9227 if (firstDisplay == StyleDisplay::RubyBaseContainer) {
9228 return;
9229 }
9230 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"
, 9231); MOZ_PretendNoReturn(); } } while (0)
9231 "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"
, 9231); MOZ_PretendNoReturn(); } } while (0)
;
9232
9233 const PseudoParentData& pseudoData =
9234 sPseudoParentData[eTypeRubyBaseContainer];
9235 RefPtr<ComputedStyle> pseudoStyle =
9236 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9237 pseudoData.mPseudoType, aParentFrame->Style());
9238 FrameConstructionItem* newItem = new (this) FrameConstructionItem(
9239 &pseudoData.mFCData,
9240 // Use the content of the parent frame
9241 aParentFrame->GetContent(), pseudoStyle.forget(), true);
9242 newItem->mIsAllInline = true;
9243 newItem->mChildItems.SetParentHasNoShadowDOM(true);
9244 iter.InsertItem(newItem);
9245}
9246
9247#ifdef DEBUG1
9248/**
9249 * Returns true iff aFrame should be wrapped in an anonymous flex/grid item,
9250 * rather than being a direct child of aContainerFrame.
9251 *
9252 * NOTE: aContainerFrame must be a flex or grid container - this function is
9253 * purely for sanity-checking the children of these container types.
9254 * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
9255 * logic (which operates a bit earlier, on FCData instead of frames).
9256 */
9257static bool FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
9258 const nsIFrame* aFrame) {
9259 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"
, 9259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContainerFrame->IsFlexOrGridContainer()"
")"); do { *((volatile int*)__null) = 9259; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9260
9261 // Any line-participant frames (e.g. text) definitely want to be wrapped in
9262 // an anonymous flex/grid item.
9263 if (aFrame->IsLineParticipant()) {
9264 return true;
9265 }
9266
9267 // If the container is a -webkit-{inline-}box container, then placeholders
9268 // also need to be wrapped, for compatibility.
9269 if (IsFlexContainerForLegacyWebKitBox(aContainerFrame) &&
9270 aFrame->IsPlaceholderFrame()) {
9271 return true;
9272 }
9273
9274 return false;
9275}
9276#endif
9277
9278static void VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
9279 const nsFrameList& aChildren) {
9280#ifdef DEBUG1
9281 if (!aParentFrame->IsFlexOrGridContainer()) {
9282 return;
9283 }
9284
9285 bool prevChildWasAnonItem = false;
9286 for (const nsIFrame* child : aChildren) {
9287 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"
, 9288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9288 "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"
, 9288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9289 if (IsAnonymousItem(child)) {
9290 AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
9291 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"
, 9291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prevChildWasAnonItem"
") (" "two anon items in a row" ")"); do { *((volatile int*)
__null) = 9291; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9292 nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
9293 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"
, 9293); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstWrappedChild"
") (" "anonymous item shouldn't be empty" ")"); do { *((volatile
int*)__null) = 9293; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9294 prevChildWasAnonItem = true;
9295 } else {
9296 prevChildWasAnonItem = false;
9297 }
9298 }
9299#endif
9300}
9301
9302static bool FrameHasOnlyPlaceholderPrevSiblings(const nsIFrame* aFrame) {
9303 // Check for prev siblings, ignoring placeholder frames.
9304 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"
, 9304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9304; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9305 const nsIFrame* prevSibling = aFrame;
9306 do {
9307 prevSibling = prevSibling->GetPrevSibling();
9308 } while (prevSibling && prevSibling->IsPlaceholderFrame());
9309 return !prevSibling;
9310}
9311
9312static bool FrameHasOnlyPlaceholderNextSiblings(const nsIFrame* aFrame) {
9313 // Check for next siblings, ignoring placeholder frames.
9314 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"
, 9314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9314; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9315 const nsIFrame* nextSibling = aFrame;
9316 do {
9317 nextSibling = nextSibling->GetNextSibling();
9318 } while (nextSibling && nextSibling->IsPlaceholderFrame());
9319 return !nextSibling;
9320}
9321
9322static void SetPageValues(nsIFrame* const aFrame,
9323 const nsAtom* const aAutoValue,
9324 const nsAtom* const aStartValue,
9325 const nsAtom* const aEndValue) {
9326 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"
, 9326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAutoValue"
") (" "Auto page value should never be null" ")"); do { *((volatile
int*)__null) = 9326; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9327 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"
, 9327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartValue || aEndValue"
") (" "Should not have called with no values" ")"); do { *((
volatile int*)__null) = 9327; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9328 nsIFrame::PageValues* pageValues =
9329 aFrame->GetProperty(nsIFrame::PageValuesProperty());
9330
9331 if (aStartValue) {
9332 if (aStartValue == aAutoValue) {
9333 // If the page value struct already exists, set the start value to null
9334 // to indicate the auto value.
9335 if (pageValues) {
9336 pageValues->mStartPageValue = nullptr;
9337 }
9338 } else {
9339 // The start value is not auto, so we need to store it, creating the
9340 // page values struct if it does not already exist.
9341 if (!pageValues) {
9342 pageValues = new nsIFrame::PageValues();
9343 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9344 }
9345 pageValues->mStartPageValue = aStartValue;
9346 }
9347 }
9348 if (aEndValue) {
9349 if (aEndValue == aAutoValue) {
9350 // If the page value struct already exists, set the end value to null
9351 // to indicate the auto value.
9352 if (pageValues) {
9353 pageValues->mEndPageValue = nullptr;
9354 }
9355 } else {
9356 // The end value is not auto, so we need to store it, creating the
9357 // page values struct if it does not already exist.
9358 if (!pageValues) {
9359 pageValues = new nsIFrame::PageValues();
9360 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9361 }
9362 pageValues->mEndPageValue = aEndValue;
9363 }
9364 }
9365}
9366
9367inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
9368 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9369 nsContainerFrame* aParentFrame, bool aParentIsWrapperAnonBox,
9370 nsFrameList& aFrameList) {
9371#ifdef DEBUG1
9372 if (aParentFrame->StyleContent()->mContent.IsNone() &&
9373 StaticPrefs::layout_css_element_content_none_enabled()) {
9374 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9375 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"
, 9376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9376 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"
, 9376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9377 }
9378 }
9379
9380 // The assertion condition should match the logic in
9381 // MaybePushFloatContainingBlock().
9382 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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9383 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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9384 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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9385 "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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9386 "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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9387 "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"
, 9387); 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) = 9387
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9388 aState.mFloatCBCandidate = nullptr;
9389#endif
9390
9391 // Ensure aParentIsWrapperAnonBox is correct. We _could_ compute it directly,
9392 // but it would be a bit slow, which is why we pass it from callers, who have
9393 // that information offhand in many cases.
9394 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"
, 9394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox"
")"); do { *((volatile int*)__null) = 9394; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9395
9396 // Note: we explicitly exclude TableColGroupFrame because it doesn't
9397 // have the FCDATA_IS_WRAPPER_ANON_BOX on pseudos so aParentIsWrapperAnonBox
9398 // is false for such pseudos (see sPseudoParentData below).
9399 if (!aParentIsWrapperAnonBox && aState.mHasRenderedLegend &&
9400 aParentFrame->GetContent()->IsHTMLElement(nsGkAtoms::fieldset) &&
9401 !aParentFrame->IsTableColGroupFrame()) {
9402 DebugOnly<bool> found = false;
9403 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9404 if (iter.item().mIsRenderedLegend) {
9405 // This makes the rendered legend the first frame in the fieldset child
9406 // list which makes keyboard traversal follow the visual order.
9407 nsFieldSetFrame* fieldSetFrame = GetFieldSetFrameFor(aParentFrame);
9408 nsFrameList renderedLegend;
9409 ConstructFramesFromItem(aState, iter, fieldSetFrame, renderedLegend);
9410 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"
, 9411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9411 "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"
, 9411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9412 fieldSetFrame->InsertFrames(FrameChildListID::Principal, nullptr,
9413 nullptr, std::move(renderedLegend));
9414 FCItemIterator next = iter;
9415 next.Next();
9416 iter.DeleteItemsTo(this, next);
9417 found = true;
9418 break;
9419 }
9420 }
9421 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"
, 9421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ") ("
"should have found our rendered legend" ")"); do { *((volatile
int*)__null) = 9421; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9422 }
9423
9424 CreateNeededPseudoContainers(aState, aItems, aParentFrame);
9425 CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
9426 CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
9427 CreateNeededPseudoSiblings(aState, aItems, aParentFrame);
9428
9429 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9430 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"
, 9432); 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) = 9432; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9431 "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"
, 9432); 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) = 9432; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9432 "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"
, 9432); 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) = 9432; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9433 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"
, 9434); MOZ_PretendNoReturn(); } } while (0)
9434 "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"
, 9434); MOZ_PretendNoReturn(); } } while (0)
;
9435 ConstructFramesFromItem(aState, iter, aParentFrame, aFrameList);
9436 }
9437
9438 VerifyGridFlexContainerChildren(aParentFrame, aFrameList);
9439
9440 // Calculate and propagate page-name values for each frame in the frame list.
9441 // We do not want to compute and propagate page-name values from frames that
9442 // are children of any subclasses of block frames, but not actually a block
9443 // frame. The page-name property does not apply to frames which cannot create
9444 // class A breakpoints (currently no subclass of BlockFrame can). Because the
9445 // property does not apply, those children also cannot propagate page-name
9446 // values.
9447 // This assumption helps avoid unnecessarily handling page-names for frames
9448 // such as form controls, which also avoids bug 1819468.
9449 if (aState.mPresContext->IsPaginated() && aParentFrame->IsBlockFrame()) {
9450 // Set the start/end page values while iterating the frame list, to walk
9451 // up the frame tree only once after iterating the frame list.
9452 // This also avoids extra property lookups on these frames.
9453 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"
, 9455); 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) = 9455; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9454 "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"
, 9455); 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) = 9455; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9455 "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"
, 9455); 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) = 9455; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9456 // Even though we store null for page values that equal the "auto" resolved
9457 // value on frames, we always want startPageValue/endPageValue to be the
9458 // actual atoms reflecting the start/end values. This is because when we
9459 // propagate the values up the frame tree, we will need to compare them to
9460 // the auto value for each ancestor. This value might be different than the
9461 // auto value for this frame.
9462 const nsAtom* startPageValue = nullptr;
9463 const nsAtom* endPageValue = nullptr;
9464 for (nsIFrame* f : aFrameList) {
9465 if (f->IsPlaceholderFrame()) {
9466 continue;
9467 }
9468 // Resolve auto against the parent frame's used page name, which has been
9469 // determined and set on aState.mAutoPageNameValue. If this item is not
9470 // block-level then we use the value that auto resolves to.
9471 //
9472 // This is to achieve the propagation behavior described in the spec:
9473 //
9474 // "A start page value and end page value is determined for each box as
9475 // the value (if any) propagated from its first or last child box
9476 // (respectively), else the used value on the box itself."
9477 //
9478 // "A child propagates its own start or end page value if and only if the
9479 // page property applies to it."
9480 //
9481 // The page property only applies to "boxes that create class A break
9482 // points". When taken together, this means that non block-level children
9483 // do not propagate start/end page values, and instead we use "the used
9484 // value on the box itself", the "box itself" being aParentFrame. This
9485 // value has been determined and saved as aState.mAutoPageNameValue
9486 //
9487 // https://www.w3.org/TR/css-page-3/#using-named-pages
9488 // https://www.w3.org/TR/css-break-3/#btw-blocks
9489 const StylePageName& pageName = f->StylePage()->mPage;
9490 const nsAtom* const pageNameAtom =
9491 (pageName.IsPageName() && f->IsBlockOutside())
9492 ? pageName.AsPageName().AsAtom()
9493 : aState.mAutoPageNameValue;
9494 nsIFrame::PageValues* pageValues =
9495 f->GetProperty(nsIFrame::PageValuesProperty());
9496 // If this frame has any children, it will already have had its page
9497 // values set at this point. However, if no page values have been set,
9498 // we must ensure that the appropriate PageValuesProperty value has been
9499 // set.
9500 // If the page name is equal to the auto value, then PageValuesProperty
9501 // should remain null to indicate that the start/end values are both
9502 // equal to the auto value.
9503 if (pageNameAtom != aState.mAutoPageNameValue && !pageValues) {
9504 pageValues = new nsIFrame::PageValues{pageNameAtom, pageNameAtom};
9505 f->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9506 }
9507 // We don't want to use GetStartPageValue() or GetEndPageValue(), as each
9508 // requires a property lookup which we can avoid here.
9509 if (!startPageValue) {
9510 startPageValue = (pageValues && pageValues->mStartPageValue)
9511 ? pageValues->mStartPageValue.get()
9512 : aState.mAutoPageNameValue;
9513 }
9514 endPageValue = (pageValues && pageValues->mEndPageValue)
9515 ? pageValues->mEndPageValue.get()
9516 : aState.mAutoPageNameValue;
9517 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"
, 9518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9518; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9518 "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"
, 9518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9518; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9519 }
9520 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"
, 9521); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9521; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9521 "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"
, 9521); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9521; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9522 if (startPageValue) {
9523 // Walk up the frame tree from our parent frame, propagating start and
9524 // end page values.
9525 // As we go, if we find that, for a frame, we are not contributing one of
9526 // the start/end page values, then our subtree will not contribute this
9527 // value from that frame onward. startPageValue/endPageValue are set to
9528 // null to indicate this.
9529 // Stop iterating when we are not contributing either start or end
9530 // values, when we hit the root frame (no parent), or when we find a
9531 // frame that is not a block frame.
9532 for (nsContainerFrame* ancestorFrame = aParentFrame;
9533 (startPageValue || endPageValue) && ancestorFrame &&
9534 ancestorFrame->IsBlockFrame();
9535 ancestorFrame = ancestorFrame->GetParent()) {
9536 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"
, 9537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9537; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9537 "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"
, 9537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9537; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9538 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"
, 9540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9539 "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"
, 9540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9540 "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"
, 9540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9540; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9541 {
9542 // Get what the auto value is, based on this frame's parent.
9543 // For the root frame, `auto` resolves to the empty atom.
9544 const nsContainerFrame* const parent = ancestorFrame->GetParent();
9545 const nsAtom* const parentAuto = MOZ_LIKELY(parent)(__builtin_expect(!!(parent), 1))
9546 ? parent->GetAutoPageValue()
9547 : nsGkAtoms::_empty;
9548 SetPageValues(ancestorFrame, parentAuto, startPageValue,
9549 endPageValue);
9550 }
9551 // Once we stop contributing start/end values, we know there is a
9552 // sibling subtree that contributed that value to our shared parent
9553 // instead of our starting frame's subtree. This means once
9554 // startPageValue/endPageValue becomes null, indicating that we are no
9555 // longer contributing that page value, it should stay null and we no
9556 // longer need to check for siblings in that direction.
9557 if (startPageValue &&
9558 !FrameHasOnlyPlaceholderPrevSiblings(ancestorFrame)) {
9559 startPageValue = nullptr;
9560 }
9561 if (endPageValue &&
9562 !FrameHasOnlyPlaceholderNextSiblings(ancestorFrame)) {
9563 endPageValue = nullptr;
9564 }
9565 }
9566 }
9567 }
9568
9569 if (aParentIsWrapperAnonBox) {
9570 for (nsIFrame* f : aFrameList) {
9571 f->SetParentIsWrapperAnonBox();
9572 }
9573 }
9574}
9575
9576void nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
9577 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
9578 const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
9579 FrameConstructionItemList& aItemsToConstruct,
9580 const AutoFrameConstructionPageName&) {
9581 for (const auto& info : aAnonymousItems) {
9582 nsIContent* content = info.mContent;
9583 // Gecko-styled nodes should have no pending restyle flags.
9584 // Assert some things about this content
9585 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"
, 9587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9587; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9586 (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"
, 9587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9587; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9587 "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"
, 9587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9587; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9588 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"
, 9588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->GetPrimaryFrame()"
") (" "Should have no existing frame" ")"); do { *((volatile
int*)__null) = 9588; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9589 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"
, 9590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9590; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9590 "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"
, 9590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9590; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9591
9592 // Make sure we eagerly performed the servo cascade when the anonymous
9593 // nodes were created.
9594 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"
, 9594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsElement() || content->AsElement()->HasServoData()"
")"); do { *((volatile int*)__null) = 9594; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9595
9596 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(content);
9597
9598 AddFrameConstructionItemsInternal(aState, content, aFrame, true,
9599 computedStyle, {ItemFlag::AllowPageBreak},
9600 aItemsToConstruct);
9601 }
9602}
9603
9604void nsCSSFrameConstructor::ProcessChildren(
9605 nsFrameConstructorState& aState, nsIContent* aContent,
9606 ComputedStyle* aComputedStyle, nsContainerFrame* aFrame,
9607 const bool aCanHaveGeneratedContent, nsFrameList& aFrameList,
9608 const bool aAllowBlockStyles, nsIFrame* aPossiblyLeafFrame) {
9609 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"
, 9609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have parent frame here" ")"); do { *((volatile int*)__null
) = 9609; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9610 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"
, 9612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9611 "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"
, 9612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9612 "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"
, 9612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9612; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9613
9614 const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH1026;
9615 static_assert(kMaxDepth <= UINT16_MAX(65535), "mCurrentDepth type is too narrow");
9616 AutoRestore<uint16_t> savedDepth(mCurrentDepth);
9617 if (mCurrentDepth != UINT16_MAX(65535)) {
9618 ++mCurrentDepth;
9619 }
9620
9621 if (!aPossiblyLeafFrame) {
9622 aPossiblyLeafFrame = aFrame;
9623 }
9624
9625 // XXXbz ideally, this would do all the pushing of various
9626 // containing blocks as needed, so callers don't have to do it...
9627
9628 // Check that our parent frame is a block before allowing ::first-letter/line.
9629 // E.g. <button style="display:grid"> should not allow it.
9630 const bool allowFirstPseudos =
9631 aAllowBlockStyles && aFrame->IsBlockFrameOrSubclass();
9632 bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
9633 if (allowFirstPseudos) {
9634 ShouldHaveSpecialBlockStyle(aContent, aComputedStyle, &haveFirstLetterStyle,
9635 &haveFirstLineStyle);
9636 }
9637
9638 AutoFrameConstructionItemList itemsToConstruct(this);
9639 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
9640
9641 // If we have first-letter or first-line style then frames can get
9642 // moved around so don't set these flags.
9643 if (allowFirstPseudos && !haveFirstLetterStyle && !haveFirstLineStyle) {
9644 itemsToConstruct.SetLineBoundaryAtStart(true);
9645 itemsToConstruct.SetLineBoundaryAtEnd(true);
9646 }
9647
9648 // Create any anonymous frames we need here.
9649 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
9650 GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
9651#ifdef DEBUG1
9652 for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
9653 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"
, 9654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9654; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9654 "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"
, 9654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9654; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9655 }
9656#endif
9657 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
9658 itemsToConstruct, pageNameTracker);
9659
9660 nsBlockFrame* listItem = nullptr;
9661 bool isOutsideMarker = false;
9662 if (!aPossiblyLeafFrame->IsLeaf()) {
9663 // :before/:after content should have the same style parent as normal kids.
9664 //
9665 // Note that we don't use this style for looking up things like special
9666 // block styles because in some cases involving table pseudo-frames it has
9667 // nothing to do with the parent frame's desired behavior.
9668 auto* styleParentFrame =
9669 nsIFrame::CorrectStyleParentFrame(aFrame, PseudoStyleType::NotPseudo);
9670 ComputedStyle* computedStyle = styleParentFrame->Style();
9671
9672 if (aCanHaveGeneratedContent) {
9673 if (computedStyle->StyleDisplay()->IsListItem() &&
9674 (listItem = do_QueryFrame(aFrame)) &&
9675 !styleParentFrame->IsFieldSetFrame()) {
9676 isOutsideMarker = computedStyle->StyleList()->mListStylePosition ==
9677 StyleListStylePosition::Outside;
9678 ItemFlags extraFlags;
9679 if (isOutsideMarker) {
9680 extraFlags += ItemFlag::IsForOutsideMarker;
9681 }
9682 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9683 *computedStyle, PseudoStyleType::marker,
9684 itemsToConstruct, extraFlags);
9685 }
9686 // Probe for generated content before
9687 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9688 *computedStyle, PseudoStyleType::before,
9689 itemsToConstruct);
9690 }
9691
9692 const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth)(__builtin_expect(!!(mCurrentDepth < kMaxDepth), 1));
9693 if (!addChildItems) {
9694 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"
, 9694)
;
9695 }
9696
9697 FlattenedChildIterator iter(aContent);
9698 const InsertionPoint insertion(aFrame, aContent);
9699 for (nsIContent* child = iter.GetNextChild(); child;
9700 child = iter.GetNextChild()) {
9701 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"
, 9702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9702; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9702 "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"
, 9702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9702; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9703 if (addChildItems) {
9704 AddFrameConstructionItems(aState, child, iter.ShadowDOMInvolved(),
9705 *computedStyle, insertion, itemsToConstruct);
9706 } else {
9707 ClearLazyBits(child, child->GetNextSibling());
9708 }
9709 }
9710 itemsToConstruct.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
9711
9712 if (aCanHaveGeneratedContent) {
9713 // Probe for generated content after
9714 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9715 *computedStyle, PseudoStyleType::after,
9716 itemsToConstruct);
9717 }
9718 } else {
9719 ClearLazyBits(aContent->GetFirstChild(), nullptr);
9720 }
9721
9722 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
9723 /* aParentIsWrapperAnonBox = */ false,
9724 aFrameList);
9725
9726 if (listItem) {
9727 if (auto* markerFrame = nsLayoutUtils::GetMarkerFrame(aContent)) {
9728 for (auto* childFrame : aFrameList) {
9729 if (markerFrame == childFrame) {
9730 if (isOutsideMarker) {
9731 // SetMarkerFrameForListItem will add childFrame to the
9732 // FrameChildListID::Bullet
9733 aFrameList.RemoveFrame(childFrame);
9734 auto* grandParent = listItem->GetParent()->GetParent();
9735 if (listItem->Style()->GetPseudoType() ==
9736 PseudoStyleType::columnContent &&
9737 grandParent && grandParent->IsColumnSetWrapperFrame()) {
9738 listItem = do_QueryFrame(grandParent);
9739 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"
, 9741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9740 "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"
, 9741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9741 "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"
, 9741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9742 childFrame->SetParent(listItem);
9743 }
9744 }
9745 listItem->SetMarkerFrameForListItem(childFrame);
9746 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"
, 9746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem->HasOutsideMarker() == isOutsideMarker"
")"); do { *((volatile int*)__null) = 9746; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9747#ifdef ACCESSIBILITY1
9748 if (nsAccessibilityService* accService = GetAccService()) {
9749 auto* marker = markerFrame->GetContent();
9750 accService->ContentRangeInserted(mPresShell, marker, nullptr);
9751 }
9752#endif
9753 break;
9754 }
9755 }
9756 }
9757 }
9758
9759 if (haveFirstLetterStyle) {
9760 WrapFramesInFirstLetterFrame(aFrame, aFrameList);
9761 }
9762 if (haveFirstLineStyle) {
9763 WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr, aFrameList);
9764 }
9765}
9766
9767//----------------------------------------------------------------------
9768
9769// Support for :first-line style
9770
9771// Special routine to handle placing a list of frames into a block
9772// frame that has first-line style. The routine ensures that the first
9773// collection of inline frames end up in a first-line frame.
9774// NOTE: aState may have containing block information related to a
9775// different part of the frame tree than where the first line occurs.
9776// In particular aState may be set up for where ContentInserted or
9777// ContentAppended is inserting content, which may be some
9778// non-first-in-flow continuation of the block to which the first-line
9779// belongs. So this function needs to be careful about how it uses
9780// aState.
9781void nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
9782 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9783 nsContainerFrame* aBlockFrame, nsFirstLineFrame* aLineFrame,
9784 nsFrameList& aFrameList) {
9785 // Extract any initial inline frames from aFrameList so we can put them
9786 // in the first-line.
9787 nsFrameList firstLineChildren =
9788 aFrameList.Split([](nsIFrame* f) { return !f->IsInlineOutside(); });
9789
9790 if (firstLineChildren.IsEmpty()) {
9791 // Nothing is supposed to go into the first-line; nothing to do
9792 return;
9793 }
9794
9795 if (!aLineFrame) {
9796 // Create line frame
9797 ComputedStyle* parentStyle = nsIFrame::CorrectStyleParentFrame(
9798 aBlockFrame, PseudoStyleType::firstLine)
9799 ->Style();
9800 RefPtr<ComputedStyle> firstLineStyle =
9801 GetFirstLineStyle(aBlockContent, parentStyle);
9802
9803 aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
9804
9805 // Initialize the line frame
9806 InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
9807
9808 // The lineFrame will be the block's first child; the rest of the
9809 // frame list (after lastInlineFrame) will be the second and
9810 // subsequent children; insert lineFrame into aFrameList.
9811 aFrameList.InsertFrame(nullptr, nullptr, aLineFrame);
9812
9813 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"
, 9814); MOZ_PretendNoReturn(); } } while (0)
9814 "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"
, 9814); MOZ_PretendNoReturn(); } } while (0)
;
9815 }
9816
9817 // Give the inline frames to the lineFrame <b>after</b> reparenting them
9818 ReparentFrames(this, aLineFrame, firstLineChildren, true);
9819 if (aLineFrame->PrincipalChildList().IsEmpty() &&
9820 aLineFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
9821 aLineFrame->SetInitialChildList(FrameChildListID::Principal,
9822 std::move(firstLineChildren));
9823 } else {
9824 AppendFrames(aLineFrame, FrameChildListID::Principal,
9825 std::move(firstLineChildren));
9826 }
9827}
9828
9829// Special routine to handle appending a new frame to a block frame's
9830// child list. Takes care of placing the new frame into the right
9831// place when first-line style is present.
9832void nsCSSFrameConstructor::AppendFirstLineFrames(
9833 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9834 nsContainerFrame* aBlockFrame, nsFrameList& aFrameList) {
9835 // It's possible that aBlockFrame needs to have a first-line frame
9836 // created because it doesn't currently have any children.
9837 const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
9838 if (blockKids.IsEmpty()) {
9839 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, nullptr,
9840 aFrameList);
9841 return;
9842 }
9843
9844 // Examine the last block child - if it's a first-line frame then
9845 // appended frames need special treatment.
9846 nsIFrame* lastBlockKid = blockKids.LastChild();
9847 if (!lastBlockKid->IsLineFrame()) {
9848 // No first-line frame at the end of the list, therefore there is
9849 // an intervening block between any first-line frame the frames
9850 // we are appending. Therefore, we don't need any special
9851 // treatment of the appended frames.
9852 return;
9853 }
9854
9855 nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
9856 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, lineFrame,
9857 aFrameList);
9858}
9859
9860void nsCSSFrameConstructor::CheckForFirstLineInsertion(
9861 nsIFrame* aParentFrame, nsFrameList& aFrameList) {
9862 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"
, 9863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9863; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
9863 "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"
, 9863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9863; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9864
9865 if (aFrameList.IsEmpty()) {
9866 // Happens often enough, with the caption stuff. No need to do the ancestor
9867 // walk here.
9868 return;
9869 }
9870
9871 class RestyleManager* restyleManager = RestyleManager();
9872
9873 // Check whether there's a ::first-line on the path up from aParentFrame.
9874 // Note that we can't stop until we've run out of ancestors with
9875 // pseudo-element data, because the first-letter might be somewhere way up the
9876 // tree; in particular it might be past our containing block.
9877 nsIFrame* ancestor = aParentFrame;
9878 while (ancestor) {
9879 if (!ancestor->Style()->HasPseudoElementData()) {
9880 // We know we won't find a ::first-line now.
9881 return;
9882 }
9883
9884 if (!ancestor->IsLineFrame()) {
9885 ancestor = ancestor->GetParent();
9886 continue;
9887 }
9888
9889 if (!ancestor->Style()->IsPseudoElement()) {
9890 // This is a continuation lineframe, not the first line; no need to do
9891 // anything to the styles.
9892 return;
9893 }
9894
9895 // Fix up the styles of aFrameList for ::first-line.
9896 for (nsIFrame* f : aFrameList) {
9897 restyleManager->ReparentComputedStyleForFirstLine(f);
9898 }
9899 return;
9900 }
9901}
9902
9903//----------------------------------------------------------------------
9904
9905// First-letter support
9906
9907// Determine how many characters in the text fragment apply to the
9908// first letter
9909static int32_t FirstLetterCount(const nsTextFragment* aFragment) {
9910 int32_t count = 0;
9911 int32_t firstLetterLength = 0;
9912
9913 const uint32_t n = aFragment->GetLength();
9914 for (uint32_t i = 0; i < n; i++) {
9915 const char16_t ch = aFragment->CharAt(i);
9916 // FIXME: take content language into account when deciding whitespace.
9917 if (dom::IsSpaceCharacter(ch)) {
9918 if (firstLetterLength) {
9919 break;
9920 }
9921 count++;
9922 continue;
9923 }
9924 // XXX I18n
9925 if ((ch == '\'') || (ch == '\"')) {
9926 if (firstLetterLength) {
9927 break;
9928 }
9929 // keep looping
9930 firstLetterLength = 1;
9931 } else {
9932 count++;
9933 break;
9934 }
9935 }
9936
9937 return count;
9938}
9939
9940static bool NeedFirstLetterContinuation(Text* aText) {
9941 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"
, 9941); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aText" ") ("
"null ptr" ")"); do { *((volatile int*)__null) = 9941; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
9942 int32_t flc = FirstLetterCount(&aText->TextFragment());
9943 int32_t tl = aText->TextDataLength();
9944 return flc < tl;
9945}
9946
9947static bool IsFirstLetterContent(Text* aText) {
9948 return aText->TextDataLength() && !aText->TextIsOnlyWhitespace();
9949}
9950
9951/**
9952 * Create a letter frame, only make it a floating frame.
9953 */
9954nsFirstLetterFrame* nsCSSFrameConstructor::CreateFloatingLetterFrame(
9955 nsFrameConstructorState& aState, Text* aTextContent, nsIFrame* aTextFrame,
9956 nsContainerFrame* aParentFrame, ComputedStyle* aParentStyle,
9957 ComputedStyle* aComputedStyle, nsFrameList& aResult) {
9958 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"
, 9958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentStyle"
")"); do { *((volatile int*)__null) = 9958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9959
9960 nsFirstLetterFrame* letterFrame =
9961 NS_NewFloatingFirstLetterFrame(mPresShell, aComputedStyle);
9962 // We don't want to use a text content for a non-text frame (because we want
9963 // its primary frame to be a text frame).
9964 nsIContent* letterContent = aParentFrame->GetContent();
9965 nsContainerFrame* containingBlock =
9966 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
9967 InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
9968
9969 // Init the text frame to refer to the letter frame.
9970 //
9971 // Make sure we get a proper style for it (the one passed in is for the letter
9972 // frame and will have the float property set on it; the text frame shouldn't
9973 // have that set).
9974 ServoStyleSet* styleSet = mPresShell->StyleSet();
9975 RefPtr<ComputedStyle> textSC =
9976 styleSet->ResolveStyleForText(aTextContent, aComputedStyle);
9977 aTextFrame->SetComputedStyleWithoutNotification(textSC);
9978 InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
9979
9980 // And then give the text frame to the letter frame
9981 SetInitialSingleChild(letterFrame, aTextFrame);
9982
9983 // See if we will need to continue the text frame (does it contain
9984 // more than just the first-letter text or not?) If it does, then we
9985 // create (in advance) a continuation frame for it.
9986 nsIFrame* nextTextFrame = nullptr;
9987 if (NeedFirstLetterContinuation(aTextContent)) {
9988 // Create continuation
9989 nextTextFrame = CreateContinuingFrame(aTextFrame, aParentFrame);
9990 RefPtr<ComputedStyle> newSC =
9991 styleSet->ResolveStyleForText(aTextContent, aParentStyle);
9992 nextTextFrame->SetComputedStyle(newSC);
9993 }
9994
9995 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"
, 9995); MOZ_PretendNoReturn(); } } while (0)
;
9996 // Put the new float before any of the floats in the block we're doing
9997 // first-letter for, that is, before any floats whose parent is
9998 // containingBlock.
9999 nsIFrame* prevSibling = nullptr;
10000 for (nsIFrame* f : aState.mFloatedList) {
10001 if (f->GetParent() == containingBlock) {
10002 break;
10003 }
10004 prevSibling = f;
10005 }
10006
10007 aState.AddChild(letterFrame, aResult, letterContent, aParentFrame, false,
10008 true, true, prevSibling);
10009
10010 if (nextTextFrame) {
10011 aResult.AppendFrame(nullptr, nextTextFrame);
10012 }
10013
10014 return letterFrame;
10015}
10016
10017/**
10018 * Create a new letter frame for aTextFrame. The letter frame will be
10019 * a child of aParentFrame.
10020 */
10021void nsCSSFrameConstructor::CreateLetterFrame(
10022 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10023 Text* aTextContent, nsContainerFrame* aParentFrame, nsFrameList& aResult) {
10024 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"
, 10024); MOZ_PretendNoReturn(); } } while (0)
;
10025
10026 // Get a ComputedStyle for the first-letter-frame.
10027 //
10028 // Keep this in sync with nsBlockFrame::UpdatePseudoElementStyles.
10029 nsIFrame* parentFrame = nsIFrame::CorrectStyleParentFrame(
10030 aParentFrame, PseudoStyleType::firstLetter);
10031
10032 ComputedStyle* parentComputedStyle = parentFrame->Style();
10033 ComputedStyle* parentComputedStyleIgnoringFirstLine = parentComputedStyle;
10034 if (parentFrame->IsLineFrame()) {
10035 parentComputedStyleIgnoringFirstLine =
10036 nsIFrame::CorrectStyleParentFrame(aBlockFrame,
10037 PseudoStyleType::firstLetter)
10038 ->Style();
10039 }
10040
10041 // Use content from containing block so that we can actually
10042 // find a matching style rule.
10043 nsIContent* blockContent = aBlockFrame->GetContent();
10044
10045 // Create first-letter style rule, ignoring first line. If we already have a
10046 // first-line we'll reparent the style below.
10047 RefPtr<ComputedStyle> sc =
10048 GetFirstLetterStyle(blockContent, parentComputedStyleIgnoringFirstLine);
10049
10050 if (sc) {
10051 if (parentComputedStyleIgnoringFirstLine != parentComputedStyle) {
10052 sc = mPresShell->StyleSet()->ReparentComputedStyle(
10053 sc, parentComputedStyle, parentComputedStyle,
10054 blockContent->AsElement());
10055 }
10056
10057 RefPtr<ComputedStyle> textSC =
10058 mPresShell->StyleSet()->ResolveStyleForText(aTextContent, sc);
10059
10060 // Create a new text frame (the original one will be discarded)
10061 // pass a temporary stylecontext, the correct one will be set
10062 // later. Start off by unsetting the primary frame for
10063 // aTextContent, so it's no longer pointing to the to-be-destroyed
10064 // frame.
10065 // XXXbz it would be really nice to destroy the old frame _first_,
10066 // then create the new one, so we could avoid this hack.
10067 aTextContent->SetPrimaryFrame(nullptr);
10068 nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
10069
10070 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"
, 10071); MOZ_PretendNoReturn(); } } while (0)
10071 "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"
, 10071); MOZ_PretendNoReturn(); } } while (0)
;
10072 nsFrameConstructorState state(
10073 mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
10074 GetAbsoluteContainingBlock(aParentFrame, ABS_POS), aBlockContinuation);
10075
10076 // Create the right type of first-letter frame
10077 const nsStyleDisplay* display = sc->StyleDisplay();
10078 nsFirstLetterFrame* letterFrame;
10079 if (display->IsFloatingStyle() && !aParentFrame->IsInSVGTextSubtree()) {
10080 // Make a floating first-letter frame
10081 letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
10082 aParentFrame, parentComputedStyle,
10083 sc, aResult);
10084 } else {
10085 // Make an inflow first-letter frame
10086 letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
10087
10088 // Initialize the first-letter-frame. We don't want to use a text
10089 // content for a non-text frame (because we want its primary frame to
10090 // be a text frame).
10091 nsIContent* letterContent = aParentFrame->GetContent();
10092 letterFrame->Init(letterContent, aParentFrame, nullptr);
10093
10094 InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
10095
10096 SetInitialSingleChild(letterFrame, textFrame);
10097 aResult.Clear();
10098 aResult.AppendFrame(nullptr, letterFrame);
10099 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"
, 10100); MOZ_PretendNoReturn(); } } while (0)
10100 "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"
, 10100); MOZ_PretendNoReturn(); } } while (0)
;
10101 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10102 }
10103 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"
, 10105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10105; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10104 !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"
, 10105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10105; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10105 "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"
, 10105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10105; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10106 auto parent =
10107 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10108 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10109 parent = static_cast<nsContainerFrame*>(
10110 parent->GetParent()->FirstContinuation());
10111 }
10112 parent->SetHasFirstLetterChild();
10113 aBlockFrame->SetProperty(nsContainerFrame::FirstLetterProperty(),
10114 letterFrame);
10115 aTextContent->SetPrimaryFrame(textFrame);
10116 }
10117}
10118
10119void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10120 nsContainerFrame* aBlockFrame, nsFrameList& aBlockFrames) {
10121 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10122
10123 nsContainerFrame* parentFrame = nullptr;
10124 nsIFrame* textFrame = nullptr;
10125 nsIFrame* prevFrame = nullptr;
10126 nsFrameList letterFrames;
10127 bool stopLooking = false;
10128 WrapFramesInFirstLetterFrame(
10129 aBlockFrame, aBlockFrame, aBlockFrame, aBlockFrames.FirstChild(),
10130 &parentFrame, &textFrame, &prevFrame, letterFrames, &stopLooking);
10131 if (!parentFrame) {
10132 return;
10133 }
10134 DestroyContext context(mPresShell);
10135 if (parentFrame == aBlockFrame) {
10136 // Take textFrame out of the block's frame list and substitute the
10137 // letter frame(s) instead.
10138 aBlockFrames.DestroyFrame(context, textFrame);
10139 aBlockFrames.InsertFrames(nullptr, prevFrame, std::move(letterFrames));
10140 } else {
10141 // Take the old textFrame out of the inline parent's child list
10142 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10143
10144 // Insert in the letter frame(s)
10145 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10146 std::move(letterFrames));
10147 }
10148}
10149
10150void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10151 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10152 nsContainerFrame* aParentFrame, nsIFrame* aParentFrameList,
10153 nsContainerFrame** aModifiedParent, nsIFrame** aTextFrame,
10154 nsIFrame** aPrevFrame, nsFrameList& aLetterFrames, bool* aStopLooking) {
10155 nsIFrame* prevFrame = nullptr;
10156 nsIFrame* frame = aParentFrameList;
10157
10158 // This loop attempts to implement "Finding the First Letter":
10159 // https://drafts.csswg.org/css-pseudo-4/#application-in-css
10160 // FIXME: we don't handle nested blocks correctly yet though (bug 214004)
10161 while (frame) {
10162 nsIFrame* nextFrame = frame->GetNextSibling();
10163
10164 // Skip all ::markers and placeholders.
10165 if (frame->Style()->GetPseudoType() == PseudoStyleType::marker ||
10166 frame->IsPlaceholderFrame()) {
10167 prevFrame = frame;
10168 frame = nextFrame;
10169 continue;
10170 }
10171 LayoutFrameType frameType = frame->Type();
10172 if (LayoutFrameType::Text == frameType) {
10173 // Wrap up first-letter content in a letter frame
10174 Text* textContent = frame->GetContent()->AsText();
10175 if (IsFirstLetterContent(textContent)) {
10176 // Create letter frame to wrap up the text
10177 CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
10178 aParentFrame, aLetterFrames);
10179
10180 // Provide adjustment information for parent
10181 *aModifiedParent = aParentFrame;
10182 *aTextFrame = frame;
10183 *aPrevFrame = prevFrame;
10184 *aStopLooking = true;
10185 return;
10186 }
10187 } else if (IsInlineFrame(frame) && frameType != LayoutFrameType::Br) {
10188 nsIFrame* kids = frame->PrincipalChildList().FirstChild();
10189 WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
10190 static_cast<nsContainerFrame*>(frame), kids,
10191 aModifiedParent, aTextFrame, aPrevFrame,
10192 aLetterFrames, aStopLooking);
10193 if (*aStopLooking) {
10194 return;
10195 }
10196 } else {
10197 // This will stop us looking to create more letter frames. For
10198 // example, maybe the frame-type is "letterFrame" or
10199 // "placeholderFrame". This keeps us from creating extra letter
10200 // frames, and also prevents us from creating letter frames when
10201 // the first real content child of a block is not text (e.g. an
10202 // image, hr, etc.)
10203 *aStopLooking = true;
10204 break;
10205 }
10206
10207 prevFrame = frame;
10208 frame = nextFrame;
10209 }
10210}
10211
10212static nsIFrame* FindFirstLetterFrame(nsIFrame* aFrame,
10213 FrameChildListID aListID) {
10214 for (nsIFrame* f : aFrame->GetChildList(aListID)) {
10215 if (f->IsLetterFrame()) {
10216 return f;
10217 }
10218 }
10219 return nullptr;
10220}
10221
10222static void ClearHasFirstLetterChildFrom(nsContainerFrame* aParentFrame) {
10223 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"
, 10223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 10223; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10224 auto* parent =
10225 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10226 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10227 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"
, 10227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10227; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10228 parent = static_cast<nsContainerFrame*>(
10229 parent->GetParent()->FirstContinuation());
10230 }
10231 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"
, 10231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10231; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10232 parent->ClearHasFirstLetterChild();
10233}
10234
10235void nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
10236 PresShell* aPresShell, nsIFrame* aBlockFrame) {
10237 // Look for the first letter frame on the FrameChildListID::Float, then
10238 // FrameChildListID::PushedFloats.
10239 nsIFrame* floatFrame =
10240 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::Float);
10241 if (!floatFrame) {
10242 floatFrame =
10243 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::PushedFloats);
10244 if (!floatFrame) {
10245 return;
10246 }
10247 }
10248
10249 // Take the text frame away from the letter frame (so it isn't
10250 // destroyed when we destroy the letter frame).
10251 nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
10252 if (!textFrame) {
10253 return;
10254 }
10255
10256 // Discover the placeholder frame for the letter frame
10257 nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame();
10258 if (!placeholderFrame) {
10259 // Somethings really wrong
10260 return;
10261 }
10262 nsContainerFrame* parentFrame = placeholderFrame->GetParent();
10263 if (!parentFrame) {
10264 // Somethings really wrong
10265 return;
10266 }
10267
10268 ClearHasFirstLetterChildFrom(parentFrame);
10269
10270 // Create a new text frame with the right style that maps all of the content
10271 // that was previously part of the letter frame (and probably continued
10272 // elsewhere).
10273 ComputedStyle* parentSC = parentFrame->Style();
10274 nsIContent* textContent = textFrame->GetContent();
10275 if (!textContent) {
10276 return;
10277 }
10278 RefPtr<ComputedStyle> newSC =
10279 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10280 nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
10281 newTextFrame->Init(textContent, parentFrame, nullptr);
10282
10283 // Destroy the old text frame's continuations (the old text frame
10284 // will be destroyed when its letter frame is destroyed).
10285 nsIFrame* frameToDelete = textFrame->LastContinuation();
10286 DestroyContext context(mPresShell);
10287 while (frameToDelete != textFrame) {
10288 nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
10289 RemoveFrame(context, FrameChildListID::Principal, frameToDelete);
10290 frameToDelete = nextFrameToDelete;
10291 }
10292
10293 nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
10294
10295 // Now that everything is set...
10296#ifdef NOISY_FIRST_LETTER
10297 printf(
10298 "RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p "
10299 "newTextFrame=%p\n",
10300 textContent.get(), textFrame, newTextFrame);
10301#endif
10302
10303 // Remove placeholder frame and the float
10304 RemoveFrame(context, FrameChildListID::Principal, placeholderFrame);
10305
10306 // Now that the old frames are gone, we can start pointing to our
10307 // new primary frame.
10308 textContent->SetPrimaryFrame(newTextFrame);
10309
10310 // Wallpaper bug 822910.
10311 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10312 if (offsetsNeedFixing) {
10313 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10314 }
10315
10316 // Insert text frame in its place
10317 InsertFrames(parentFrame, FrameChildListID::Principal, prevSibling,
10318 nsFrameList(newTextFrame, newTextFrame));
10319
10320 if (offsetsNeedFixing) {
10321 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10322 }
10323}
10324
10325void nsCSSFrameConstructor::RemoveFirstLetterFrames(
10326 PresShell* aPresShell, nsContainerFrame* aFrame,
10327 nsContainerFrame* aBlockFrame, bool* aStopLooking) {
10328 nsIFrame* prevSibling = nullptr;
10329 nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
10330
10331 while (kid) {
10332 if (kid->IsLetterFrame()) {
10333 ClearHasFirstLetterChildFrom(aFrame);
10334 nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
10335 if (!textFrame) {
10336 break;
10337 }
10338
10339 // Create a new textframe
10340 ComputedStyle* parentSC = aFrame->Style();
10341 if (!parentSC) {
10342 break;
10343 }
10344 nsIContent* textContent = textFrame->GetContent();
10345 if (!textContent) {
10346 break;
10347 }
10348 RefPtr<ComputedStyle> newSC =
10349 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10350 textFrame = NS_NewTextFrame(aPresShell, newSC);
10351 textFrame->Init(textContent, aFrame, nullptr);
10352
10353 DestroyContext context(mPresShell);
10354
10355 // Next rip out the kid and replace it with the text frame
10356 RemoveFrame(context, FrameChildListID::Principal, kid);
10357
10358 // Now that the old frames are gone, we can start pointing to our
10359 // new primary frame.
10360 textContent->SetPrimaryFrame(textFrame);
10361
10362 // Wallpaper bug 822910.
10363 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10364 if (offsetsNeedFixing) {
10365 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10366 }
10367
10368 // Insert text frame in its place
10369 InsertFrames(aFrame, FrameChildListID::Principal, prevSibling,
10370 nsFrameList(textFrame, textFrame));
10371
10372 if (offsetsNeedFixing) {
10373 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10374 }
10375
10376 *aStopLooking = true;
10377 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"
, 10378); MOZ_PretendNoReturn(); } } while (0)
10378 "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"
, 10378); MOZ_PretendNoReturn(); } } while (0)
;
10379 aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10380 break;
10381 }
10382 if (IsInlineFrame(kid)) {
10383 nsContainerFrame* kidAsContainerFrame = do_QueryFrame(kid);
10384 if (kidAsContainerFrame) {
10385 // Look inside child inline frame for the letter frame.
10386 RemoveFirstLetterFrames(aPresShell, kidAsContainerFrame, aBlockFrame,
10387 aStopLooking);
10388 if (*aStopLooking) {
10389 break;
10390 }
10391 }
10392 }
10393 prevSibling = kid;
10394 kid = kid->GetNextSibling();
10395 }
10396}
10397
10398void nsCSSFrameConstructor::RemoveLetterFrames(PresShell* aPresShell,
10399 nsContainerFrame* aBlockFrame) {
10400 aBlockFrame =
10401 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10402 aBlockFrame->RemoveProperty(nsContainerFrame::FirstLetterProperty());
10403 nsContainerFrame* continuation = aBlockFrame;
10404
10405 bool stopLooking = false;
10406 do {
10407 RemoveFloatingFirstLetterFrames(aPresShell, continuation);
10408 RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame,
10409 &stopLooking);
10410 if (stopLooking) {
10411 break;
10412 }
10413 continuation =
10414 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10415 } while (continuation);
10416}
10417
10418// Fixup the letter frame situation for the given block
10419void nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame) {
10420 aBlockFrame =
10421 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10422 nsContainerFrame* continuation = aBlockFrame;
10423
10424 nsContainerFrame* parentFrame = nullptr;
10425 nsIFrame* textFrame = nullptr;
10426 nsIFrame* prevFrame = nullptr;
10427 nsFrameList letterFrames;
10428 bool stopLooking = false;
10429 do {
10430 // XXX shouldn't this bit be set already (bug 408493), assert instead?
10431 continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10432 WrapFramesInFirstLetterFrame(
10433 aBlockFrame, continuation, continuation,
10434 continuation->PrincipalChildList().FirstChild(), &parentFrame,
10435 &textFrame, &prevFrame, letterFrames, &stopLooking);
10436 if (stopLooking) {
10437 break;
10438 }
10439 continuation =
10440 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10441 } while (continuation);
10442
10443 if (!parentFrame) {
10444 return;
10445 }
10446 // Take the old textFrame out of the parent's child list
10447 DestroyContext context(mPresShell);
10448 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10449
10450 // Insert in the letter frame(s)
10451 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10452 std::move(letterFrames));
10453}
10454
10455//----------------------------------------------------------------------
10456
10457void nsCSSFrameConstructor::ConstructBlock(
10458 nsFrameConstructorState& aState, nsIContent* aContent,
10459 nsContainerFrame* aParentFrame, nsContainerFrame* aContentParentFrame,
10460 ComputedStyle* aComputedStyle, nsContainerFrame** aNewFrame,
10461 nsFrameList& aFrameList, nsIFrame* aPositionedFrameForAbsPosContainer) {
10462 // clang-format off
10463 //
10464 // If a block frame is in a multi-column subtree, its children may need to
10465 // be chopped into runs of blocks containing column-spans and runs of
10466 // blocks containing no column-spans. Each run containing column-spans
10467 // will be wrapped by an anonymous block. See CreateColumnSpanSiblings() for
10468 // the implementation.
10469 //
10470 // If a block frame is a multi-column container, its children will need to
10471 // be processed as above. Moreover, it creates a ColumnSetWrapperFrame as
10472 // its outermost frame, and its children which have no
10473 // -moz-column-span-wrapper pseudo will be wrapped in ColumnSetFrames. See
10474 // FinishBuildingColumns() for the implementation.
10475 //
10476 // The multi-column subtree maintains the following invariants:
10477 //
10478 // 1) All the frames have the frame state bit
10479 // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR set, except for top-level
10480 // ColumnSetWrapperFrame and those children in the column-span subtrees.
10481 //
10482 // 2) The first and last frame under ColumnSetWrapperFrame are always
10483 // ColumnSetFrame.
10484 //
10485 // 3) ColumnSetFrames are linked together as continuations.
10486 //
10487 // 4) Those column-span wrappers are *not* linked together with themselves nor
10488 // with the original block frame. The continuation chain consists of the
10489 // original block frame and the original block's continuations wrapping
10490 // non-column-spans.
10491 //
10492 // For example, this HTML
10493 // <div id="x" style="column-count: 2;">
10494 // <div style="column-span: all">a</div>
10495 // <div id="y">
10496 // b
10497 // <div style="column-span: all">c</div>
10498 // <div style="column-span: all">d</div>
10499 // e
10500 // </div>
10501 // </div>
10502 // <div style="column-span: all">f</div>
10503 //
10504 // yields the following frame tree.
10505 //
10506 // A) ColumnSetWrapper (original style)
10507 // B) ColumnSet (-moz-column-set) <-- always created by BeginBuildingColumns
10508 // C) Block (-moz-column-content)
10509 // D) Block (-moz-column-span-wrapper, created by x)
10510 // E) Block (div)
10511 // F) Text ("a")
10512 // G) ColumnSet (-moz-column-set)
10513 // H) Block (-moz-column-content, created by x)
10514 // I) Block (div, y)
10515 // J) Text ("b")
10516 // K) Block (-moz-column-span-wrapper, created by x)
10517 // L) Block (-moz-column-span-wrapper, created by y)
10518 // M) Block (div, new BFC)
10519 // N) Text ("c")
10520 // O) Block (div, new BFC)
10521 // P) Text ("d")
10522 // Q) ColumnSet (-moz-column-set)
10523 // R) Block (-moz-column-content, created by x)
10524 // S) Block (div, y)
10525 // T) Text ("e")
10526 // U) Block (div, new BFC) <-- not in multi-column hierarchy
10527 // V) Text ("f")
10528 //
10529 // ColumnSet linkage described in 3): B -> G -> Q
10530 //
10531 // Block linkage described in 4): C -> H -> R and I -> S
10532 //
10533 // clang-format on
10534
10535 nsBlockFrame* blockFrame = do_QueryFrame(*aNewFrame);
10536 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"
, 10536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockFrame && blockFrame->IsBlockFrame()"
") (" "not a block frame?" ")"); do { *((volatile int*)__null
) = 10536; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
10537
10538 // Create column hierarchy if necessary.
10539 const bool needsColumn =
10540 aComputedStyle->StyleColumn()->IsColumnContainerStyle();
10541 if (needsColumn) {
10542 *aNewFrame = BeginBuildingColumns(aState, aContent, aParentFrame,
10543 blockFrame, aComputedStyle);
10544
10545 if (aPositionedFrameForAbsPosContainer == blockFrame) {
10546 aPositionedFrameForAbsPosContainer = *aNewFrame;
10547 }
10548 } else {
10549 // No need to create column hierarchy. Initialize block frame.
10550 blockFrame->SetComputedStyleWithoutNotification(aComputedStyle);
10551 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
10552 }
10553
10554 aState.AddChild(*aNewFrame, aFrameList, aContent,
10555 aContentParentFrame ? aContentParentFrame : aParentFrame);
10556 if (!mRootElementFrame) {
10557 mRootElementFrame = *aNewFrame;
10558 }
10559
10560 // We should make the outer frame be the absolute containing block,
10561 // if one is required. We have to do this because absolute
10562 // positioning must be computed with respect to the CSS dimensions
10563 // of the element, which are the dimensions of the outer block. But
10564 // we can't really do that because only blocks can have absolute
10565 // children. So use the block and try to compensate with hacks
10566 // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
10567 nsFrameConstructorSaveState absoluteSaveState;
10568 (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10569 if (aPositionedFrameForAbsPosContainer) {
10570 aState.PushAbsoluteContainingBlock(
10571 *aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
10572 }
10573
10574 nsFrameConstructorSaveState floatSaveState;
10575 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
10576
10577 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10578 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10579 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10580 }
10581
10582 // Process the child content
10583 nsFrameList childList;
10584 ProcessChildren(aState, aContent, aComputedStyle, blockFrame, true, childList,
10585 true);
10586
10587 if (!MayNeedToCreateColumnSpanSiblings(blockFrame, childList)) {
10588 // No need to create column-span siblings.
10589 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10590 std::move(childList));
10591 return;
10592 }
10593
10594 // Extract any initial non-column-span kids, and put them in block frame's
10595 // child list.
10596 nsFrameList initialNonColumnSpanKids =
10597 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10598 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10599 std::move(initialNonColumnSpanKids));
10600
10601 if (childList.IsEmpty()) {
10602 // No more kids to process (there weren't any column-span kids).
10603 return;
10604 }
10605
10606 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
10607 aState, blockFrame, childList,
10608 // If we're constructing a column container, pass nullptr as
10609 // aPositionedFrame to forbid reparenting absolute/fixed positioned frames
10610 // to column contents or column-span wrappers.
10611 needsColumn ? nullptr : aPositionedFrameForAbsPosContainer);
10612
10613 if (needsColumn) {
10614 // We're constructing a column container; need to finish building it.
10615 FinishBuildingColumns(aState, *aNewFrame, blockFrame, columnSpanSiblings);
10616 } else {
10617 // We're constructing a normal block which has column-span children in a
10618 // column hierarchy such as "x" in the following example.
10619 //
10620 // <div style="column-count: 2">
10621 // <div id="x">
10622 // <div>normal child</div>
10623 // <div style="column-span">spanner</div>
10624 // </div>
10625 // </div>
10626 aFrameList.AppendFrames(nullptr, std::move(columnSpanSiblings));
10627 }
10628
10629 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"
, 10630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10630; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10630 "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"
, 10630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10630; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10631}
10632
10633nsBlockFrame* nsCSSFrameConstructor::BeginBuildingColumns(
10634 nsFrameConstructorState& aState, nsIContent* aContent,
10635 nsContainerFrame* aParentFrame, nsContainerFrame* aColumnContent,
10636 ComputedStyle* aComputedStyle) {
10637 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"
, 10638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10638; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10638 "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"
, 10638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10638; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10639 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"
, 10640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10640; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
10640 "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"
, 10640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10640; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10641
10642 // The initial column hierarchy looks like this:
10643 //
10644 // ColumnSetWrapper (original style)
10645 // ColumnSet (-moz-column-set)
10646 // Block (-moz-column-content)
10647 //
10648 nsBlockFrame* columnSetWrapper = NS_NewColumnSetWrapperFrame(
10649 mPresShell, aComputedStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10650 InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetWrapper);
10651 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10652 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10653 columnSetWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10654 }
10655
10656 AutoFrameConstructionPageName pageNameTracker(aState, columnSetWrapper);
10657 RefPtr<ComputedStyle> columnSetStyle =
10658 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10659 PseudoStyleType::columnSet, aComputedStyle);
10660 nsContainerFrame* columnSet = NS_NewColumnSetFrame(
10661 mPresShell, columnSetStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10662 InitAndRestoreFrame(aState, aContent, columnSetWrapper, columnSet);
10663 columnSet->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10664
10665 RefPtr<ComputedStyle> blockStyle =
10666 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10667 PseudoStyleType::columnContent, columnSetStyle);
10668 aColumnContent->SetComputedStyleWithoutNotification(blockStyle);
10669 InitAndRestoreFrame(aState, aContent, columnSet, aColumnContent);
10670 aColumnContent->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10671
10672 // Set up the parent-child chain.
10673 SetInitialSingleChild(columnSetWrapper, columnSet);
10674 SetInitialSingleChild(columnSet, aColumnContent);
10675
10676 return columnSetWrapper;
10677}
10678
10679void nsCSSFrameConstructor::FinishBuildingColumns(
10680 nsFrameConstructorState& aState, nsContainerFrame* aColumnSetWrapper,
10681 nsContainerFrame* aColumnContent, nsFrameList& aColumnContentSiblings) {
10682 nsContainerFrame* prevColumnSet = aColumnContent->GetParent();
10683
10684 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"
, 10686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10686; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10685 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"
, 10686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10686; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10686 "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"
, 10686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10686; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10687
10688 // Tag the first ColumnSet to have column-span siblings so that the bit can
10689 // propagate to all the continuations. We don't want the last ColumnSet to
10690 // have this bit, so we will unset the bit for it at the end of this function.
10691 prevColumnSet->SetHasColumnSpanSiblings(true);
10692
10693 nsFrameList finalList;
10694 while (aColumnContentSiblings.NotEmpty()) {
10695 nsIFrame* f = aColumnContentSiblings.RemoveFirstChild();
10696 if (f->IsColumnSpan()) {
10697 // Do nothing for column-span wrappers. Just move it to the final
10698 // items.
10699 finalList.AppendFrame(aColumnSetWrapper, f);
10700 } else {
10701 auto* continuingColumnSet = static_cast<nsContainerFrame*>(
10702 CreateContinuingFrame(prevColumnSet, aColumnSetWrapper, false));
10703 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"
, 10704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10704 "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"
, 10704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10704; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10705
10706 f->SetParent(continuingColumnSet);
10707 SetInitialSingleChild(continuingColumnSet, f);
10708 finalList.AppendFrame(aColumnSetWrapper, continuingColumnSet);
10709 prevColumnSet = continuingColumnSet;
10710 }
10711 }
10712
10713 // Unset the bit because the last ColumnSet has no column-span siblings.
10714 prevColumnSet->SetHasColumnSpanSiblings(false);
10715
10716 aColumnSetWrapper->AppendFrames(FrameChildListID::Principal,
10717 std::move(finalList));
10718}
10719
10720bool nsCSSFrameConstructor::MayNeedToCreateColumnSpanSiblings(
10721 nsContainerFrame* aBlockFrame, const nsFrameList& aChildList) {
10722 if (!aBlockFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10723 // The block frame isn't in a multi-column block formatting context.
10724 return false;
10725 }
10726
10727 if (ShouldSuppressColumnSpanDescendants(aBlockFrame)) {
10728 // No need to create column-span siblings for a frame that suppresses them.
10729 return false;
10730 }
10731
10732 if (aChildList.IsEmpty()) {
10733 // No child needs to be processed.
10734 return false;
10735 }
10736
10737 // Need to actually look into the child list.
10738 return true;
10739}
10740
10741nsFrameList nsCSSFrameConstructor::CreateColumnSpanSiblings(
10742 nsFrameConstructorState& aState, nsContainerFrame* aInitialBlock,
10743 nsFrameList& aChildList, nsIFrame* aPositionedFrame) {
10744 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"
, 10744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInitialBlock->IsBlockFrameOrSubclass()"
")"); do { *((volatile int*)__null) = 10744; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10745 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"
, 10745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 10745; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10746
10747 nsIContent* const content = aInitialBlock->GetContent();
10748 nsContainerFrame* const parentFrame = aInitialBlock->GetParent();
10749 const bool isInitialBlockFloatCB = aInitialBlock->IsFloatContainingBlock();
10750
10751 nsFrameList siblings;
10752 nsContainerFrame* lastNonColumnSpanWrapper = aInitialBlock;
10753
10754 // Tag the first non-column-span wrapper to have column-span siblings so that
10755 // the bit can propagate to all the continuations. We don't want the last
10756 // wrapper to have this bit, so we will unset the bit for it at the end of
10757 // this function.
10758 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(true);
10759 do {
10760 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"
, 10760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Why call this if child list is empty?" ")"); do { *((
volatile int*)__null) = 10760; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10761 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"
, 10762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10762 "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"
, 10762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10763
10764 // Grab the consecutive column-span kids, and reparent them into a
10765 // block frame.
10766 RefPtr<ComputedStyle> columnSpanWrapperStyle =
10767 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
10768 PseudoStyleType::columnSpanWrapper);
10769 nsBlockFrame* columnSpanWrapper =
10770 NS_NewBlockFrame(mPresShell, columnSpanWrapperStyle);
10771 InitAndRestoreFrame(aState, content, parentFrame, columnSpanWrapper, false);
10772 columnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10773 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10774
10775 nsFrameList columnSpanKids =
10776 aChildList.Split([](nsIFrame* f) { return !f->IsColumnSpan(); });
10777 columnSpanKids.ApplySetParent(columnSpanWrapper);
10778 columnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10779 std::move(columnSpanKids));
10780 if (aPositionedFrame) {
10781 aState.ReparentAbsoluteItems(columnSpanWrapper);
10782 }
10783
10784 siblings.AppendFrame(nullptr, columnSpanWrapper);
10785
10786 // Grab the consecutive non-column-span kids, and reparent them into a new
10787 // continuation of the last non-column-span wrapper frame.
10788 auto* nonColumnSpanWrapper = static_cast<nsContainerFrame*>(
10789 CreateContinuingFrame(lastNonColumnSpanWrapper, parentFrame, false));
10790 nonColumnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10791 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10792 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"
, 10793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10793; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10793 "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"
, 10793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10793; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10794
10795 if (aChildList.NotEmpty()) {
10796 nsFrameList nonColumnSpanKids =
10797 aChildList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10798
10799 nonColumnSpanKids.ApplySetParent(nonColumnSpanWrapper);
10800 nonColumnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10801 std::move(nonColumnSpanKids));
10802 if (aPositionedFrame) {
10803 aState.ReparentAbsoluteItems(nonColumnSpanWrapper);
10804 }
10805 if (isInitialBlockFloatCB) {
10806 aState.ReparentFloats(nonColumnSpanWrapper);
10807 }
10808 }
10809
10810 siblings.AppendFrame(nullptr, nonColumnSpanWrapper);
10811
10812 lastNonColumnSpanWrapper = nonColumnSpanWrapper;
10813 } while (aChildList.NotEmpty());
10814
10815 // Unset the bit because the last non-column-span wrapper has no column-span
10816 // siblings.
10817 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(false);
10818
10819 return siblings;
10820}
10821
10822bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
10823 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
10824 nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
10825 if (!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10826 return false;
10827 }
10828
10829 if (aFrameList.IsEmpty()) {
10830 return false;
10831 }
10832
10833 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"
, 10835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10835
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10834 "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"
, 10835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10835
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10835 "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"
, 10835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10835
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
10836
10837 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
10838 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
10839 // We are appending a list of frames to the last continuation of a
10840 // ::-moz-column-content. This is the case where we can fix the frame tree
10841 // instead of reframing the containing block. Return false and let
10842 // AppendFramesToParent() deal with this.
10843 return false;
10844 }
10845
10846 auto HasColumnSpan = [](const nsFrameList& aList) {
10847 for (nsIFrame* f : aList) {
10848 if (f->IsColumnSpan()) {
10849 return true;
10850 }
10851 }
10852 return false;
10853 };
10854
10855 if (HasColumnSpan(aFrameList)) {
10856 // If any frame in the frame list has "column-span:all" style, i.e. a
10857 // -moz-column-span-wrapper frame, we need to reframe the multi-column
10858 // containing block.
10859 //
10860 // We can only be here if none of the new inserted nsIContent* nodes (via
10861 // ContentAppended or ContentRangeInserted) have column-span:all style, yet
10862 // some of them have column-span:all descendants. Sadly, there's no way to
10863 // detect this by checking FrameConstructionItems in WipeContainingBlock().
10864 // Otherwise, we would have already wiped the multi-column containing block.
10865 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)
10866 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)
;
10867
10868 // aFrameList can contain placeholder frames. In order to destroy their
10869 // associated out-of-flow frames properly, we need to manually flush all the
10870 // out-of-flow frames in aState to their container frames.
10871 aState.ProcessFrameInsertionsForAllLists();
10872 DestroyContext context(mPresShell);
10873 aFrameList.DestroyFrames(context);
10874 RecreateFramesForContent(
10875 GetMultiColumnContainingBlockFor(aParentFrame)->GetContent(),
10876 InsertionKind::Async);
10877 return true;
10878 }
10879
10880 return false;
10881}
10882
10883nsIFrame* nsCSSFrameConstructor::ConstructInline(
10884 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
10885 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
10886 nsFrameList& aFrameList) {
10887 // If an inline frame has non-inline kids, then we chop up the child list
10888 // into runs of blocks and runs of inlines, create anonymous block frames to
10889 // contain the runs of blocks, inline frames with our style for the runs of
10890 // inlines, and put all these frames, in order, into aFrameList.
10891 //
10892 // When there are column-span blocks in a run of blocks, instead of creating
10893 // an anonymous block to wrap them, we create multiple anonymous blocks,
10894 // wrapping runs of non-column-spans and runs of column-spans.
10895 //
10896 // We return the the first one. The whole setup is called an {ib}
10897 // split; in what follows "frames in the split" refers to the anonymous blocks
10898 // and inlines that contain our children.
10899 //
10900 // {ib} splits maintain the following invariants:
10901 // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
10902 // set.
10903 //
10904 // 2) Each frame in the split has the nsIFrame::IBSplitSibling
10905 // property pointing to the next frame in the split, except for the last
10906 // one, which does not have it set.
10907 //
10908 // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
10909 // property pointing to the previous frame in the split, except for the
10910 // first one, which does not have it set.
10911 //
10912 // 4) The first and last frame in the split are always inlines.
10913 //
10914 // 5) The frames wrapping runs of non-column-spans are linked together as
10915 // continuations. The frames wrapping runs of column-spans are *not*
10916 // linked with each other nor with other non-column-span wrappers.
10917 //
10918 // 6) The first and last frame in the chains of blocks are always wrapping
10919 // non-column-spans. Both of them are created even if they're empty.
10920 //
10921 // An invariant that is NOT maintained is that the wrappers are actually
10922 // linked via GetNextSibling linkage. A simple example is an inline
10923 // containing an inline that contains a block. The three parts of the inner
10924 // inline end up with three different parents.
10925 //
10926 // For example, this HTML:
10927 // <span>
10928 // <div>a</div>
10929 // <span>
10930 // b
10931 // <div>c</div>
10932 // </span>
10933 // d
10934 // <div>e</div>
10935 // f
10936 // </span>
10937 // Gives the following frame tree:
10938 //
10939 // Inline (outer span)
10940 // Block (anonymous, outer span)
10941 // Block (div)
10942 // Text("a")
10943 // Inline (outer span)
10944 // Inline (inner span)
10945 // Text("b")
10946 // Block (anonymous, outer span)
10947 // Block (anonymous, inner span)
10948 // Block (div)
10949 // Text("c")
10950 // Inline (outer span)
10951 // Inline (inner span)
10952 // Text("d")
10953 // Block (anonymous, outer span)
10954 // Block (div)
10955 // Text("e")
10956 // Inline (outer span)
10957 // Text("f")
10958
10959 nsIContent* const content = aItem.mContent;
10960 ComputedStyle* const computedStyle = aItem.mComputedStyle;
10961
10962 nsInlineFrame* newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
10963
10964 // Initialize the frame
10965 InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
10966
10967 // definition cannot be inside next block because the object's destructor is
10968 // significant. this is part of the fix for bug 42372
10969 nsFrameConstructorSaveState absoluteSaveState;
10970
10971 bool isAbsPosCB = newFrame->IsAbsPosContainingBlock();
10972 newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10973 if (isAbsPosCB) {
10974 // Relatively positioned frames becomes a container for child
10975 // frames that are positioned
10976 aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
10977 }
10978
10979 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10980 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10981 newFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10982 }
10983
10984 // Process the child content
10985 nsFrameList childList;
10986 ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
10987 /* aParentIsWrapperAnonBox = */ false, childList);
10988
10989 nsIFrame* firstBlock = nullptr;
10990 if (!aItem.mIsAllInline) {
10991 for (nsIFrame* f : childList) {
10992 if (f->IsBlockOutside()) {
10993 firstBlock = f;
10994 break;
10995 }
10996 }
10997 }
10998
10999 if (aItem.mIsAllInline || !firstBlock) {
11000 // This part is easy. We either already know we have no non-inline kids,
11001 // or haven't found any when constructing actual frames (the latter can
11002 // happen only if out-of-flows that we thought had no containing block
11003 // acquired one when ancestor inline frames and {ib} splits got
11004 // constructed). Just put all the kids into the single inline frame and
11005 // bail.
11006 newFrame->SetInitialChildList(FrameChildListID::Principal,
11007 std::move(childList));
11008 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
11009 return newFrame;
11010 }
11011
11012 // This inline frame contains several types of children. Therefore this frame
11013 // has to be chopped into several pieces, as described above.
11014
11015 // Grab the first inline's kids
11016 nsFrameList firstInlineKids = childList.TakeFramesBefore(firstBlock);
11017 newFrame->SetInitialChildList(FrameChildListID::Principal,
11018 std::move(firstInlineKids));
11019
11020 aFrameList.AppendFrame(nullptr, newFrame);
11021
11022 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
11023 CreateIBSiblings(aState, newFrame, isAbsPosCB, childList, aFrameList);
11024
11025 return newFrame;
11026}
11027
11028void nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
11029 nsContainerFrame* aInitialInline,
11030 bool aIsAbsPosCB,
11031 nsFrameList& aChildList,
11032 nsFrameList& aSiblings) {
11033 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"
, 11033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 11033; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11034
11035 nsIContent* content = aInitialInline->GetContent();
11036 ComputedStyle* computedStyle = aInitialInline->Style();
11037 nsContainerFrame* parentFrame = aInitialInline->GetParent();
11038
11039 // Resolve the right style for our anonymous blocks.
11040 //
11041 // The distinction in styles is needed because of CSS 2.1, section
11042 // 9.2.1.1, which says:
11043 //
11044 // When such an inline box is affected by relative positioning, any
11045 // resulting translation also affects the block-level box contained
11046 // in the inline box.
11047 RefPtr<ComputedStyle> blockSC =
11048 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
11049 PseudoStyleType::mozBlockInsideInlineWrapper, computedStyle);
11050
11051 nsContainerFrame* lastNewInline =
11052 static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
11053 do {
11054 // On entry to this loop aChildList is not empty and the first frame in it
11055 // is block-level.
11056 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"
, 11056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Should have child items" ")"); do { *((volatile int*)
__null) = 11056; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11057 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"
, 11058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11058; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11058 "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"
, 11058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11058; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11059
11060 // The initial run of blocks belongs to an anonymous block that we create
11061 // right now. The anonymous block will be the parent of these block
11062 // children of the inline.
11063 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
11064 InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
11065 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11066 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11067 }
11068
11069 // Find the first non-block child which defines the end of our block kids
11070 // and the start of our next inline's kids
11071 nsFrameList blockKids =
11072 aChildList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
11073
11074 if (!aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11075 MoveChildrenTo(aInitialInline, blockFrame, blockKids);
11076
11077 SetFrameIsIBSplit(lastNewInline, blockFrame);
11078 aSiblings.AppendFrame(nullptr, blockFrame);
11079 } else {
11080 // Extract any initial non-column-span frames, and put them in
11081 // blockFrame's child list.
11082 nsFrameList initialNonColumnSpanKids =
11083 blockKids.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
11084 MoveChildrenTo(aInitialInline, blockFrame, initialNonColumnSpanKids);
11085
11086 SetFrameIsIBSplit(lastNewInline, blockFrame);
11087 aSiblings.AppendFrame(nullptr, blockFrame);
11088
11089 if (blockKids.NotEmpty()) {
11090 // Although SetFrameIsIBSplit() will add NS_FRAME_PART_OF_IBSPLIT for
11091 // blockFrame later, we manually add the bit earlier here to make all
11092 // the continuations of blockFrame created in
11093 // CreateColumnSpanSiblings(), i.e. non-column-span wrappers, have the
11094 // bit via nsIFrame::Init().
11095 blockFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
11096
11097 nsFrameList columnSpanSiblings =
11098 CreateColumnSpanSiblings(aState, blockFrame, blockKids,
11099 aIsAbsPosCB ? aInitialInline : nullptr);
11100 aSiblings.AppendFrames(nullptr, std::move(columnSpanSiblings));
11101 }
11102 }
11103
11104 // Now grab the initial inlines in aChildList and put them into an inline
11105 // frame.
11106 nsInlineFrame* inlineFrame = NS_NewInlineFrame(mPresShell, computedStyle);
11107 InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
11108 inlineFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
11109 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11110 inlineFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11111 }
11112
11113 if (aIsAbsPosCB) {
11114 inlineFrame->MarkAsAbsoluteContainingBlock();
11115 }
11116
11117 if (aChildList.NotEmpty()) {
11118 nsFrameList inlineKids =
11119 aChildList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
11120 MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
11121 }
11122
11123 SetFrameIsIBSplit(blockFrame, inlineFrame);
11124 aSiblings.AppendFrame(nullptr, inlineFrame);
11125 lastNewInline = inlineFrame;
11126 } while (aChildList.NotEmpty());
11127
11128 SetFrameIsIBSplit(lastNewInline, nullptr);
11129}
11130
11131void nsCSSFrameConstructor::BuildInlineChildItems(
11132 nsFrameConstructorState& aState, FrameConstructionItem& aParentItem,
11133 bool aItemIsWithinSVGText, bool aItemAllowsTextPathChild) {
11134 ComputedStyle* const parentComputedStyle = aParentItem.mComputedStyle;
11135 nsIContent* const parentContent = aParentItem.mContent;
11136
11137 if (!aItemIsWithinSVGText) {
11138 if (parentComputedStyle->StyleDisplay()->IsListItem()) {
11139 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11140 *parentComputedStyle, PseudoStyleType::marker,
11141 aParentItem.mChildItems);
11142 }
11143 // Probe for generated content before
11144 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11145 *parentComputedStyle, PseudoStyleType::before,
11146 aParentItem.mChildItems);
11147 }
11148
11149 ItemFlags flags;
11150 if (aItemIsWithinSVGText) {
11151 flags += ItemFlag::IsWithinSVGText;
11152 }
11153 if (aItemAllowsTextPathChild &&
11154 aParentItem.mContent->IsSVGElement(nsGkAtoms::a)) {
11155 flags += ItemFlag::AllowTextPathChild;
11156 }
11157
11158 FlattenedChildIterator iter(parentContent);
11159 for (nsIContent* content = iter.GetNextChild(); content;
11160 content = iter.GetNextChild()) {
11161 AddFrameConstructionItems(aState, content, iter.ShadowDOMInvolved(),
11162 *parentComputedStyle, InsertionPoint(),
11163 aParentItem.mChildItems, flags);
11164 }
11165
11166 if (!aItemIsWithinSVGText) {
11167 // Probe for generated content after
11168 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11169 *parentComputedStyle, PseudoStyleType::after,
11170 aParentItem.mChildItems);
11171 }
11172
11173 aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
11174}
11175
11176// return whether it's ok to append (in the AppendFrames sense) to
11177// aParentFrame if our nextSibling is aNextSibling. aParentFrame must
11178// be an ib-split inline.
11179static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
11180 nsIFrame* aNextSibling) {
11181 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"
, 11181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInlineFrame(aParentFrame)"
") (" "Must have an inline parent here" ")"); do { *((volatile
int*)__null) = 11181; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11182
11183 do {
11184 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"
, 11185); MOZ_PretendNoReturn(); } } while (0)
11185 "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"
, 11185); MOZ_PretendNoReturn(); } } while (0)
;
11186 if (aNextSibling || aParentFrame->GetNextContinuation() ||
11187 GetIBSplitSibling(aParentFrame)) {
11188 return false;
11189 }
11190
11191 aNextSibling = aParentFrame->GetNextSibling();
11192 aParentFrame = aParentFrame->GetParent();
11193 } while (IsInlineFrame(aParentFrame));
11194
11195 return true;
11196}
11197
11198bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
11199#define TRACE(reason) \
11200 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)
11201 "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)
;
11202
11203 const LayoutFrameType frameType = aFrame->Type();
11204
11205 // FIXME(emilio): This looks terribly inefficient if you insert elements deep
11206 // in a MathML subtree.
11207 if (aFrame->IsMathMLFrame()) {
11208 TRACE("MathML");
11209 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11210 return true;
11211 }
11212
11213 // A ruby-related frame that's getting new children.
11214 // The situation for ruby is complex, especially when interacting with
11215 // spaces. It contains these two special cases apart from tables:
11216 // 1) There are effectively three types of white spaces in ruby frames
11217 // we handle differently: leading/tailing/inter-level space,
11218 // inter-base/inter-annotation space, and inter-segment space.
11219 // These three types of spaces can be converted to each other when
11220 // their sibling changes.
11221 // 2) The first effective child of a ruby frame must always be a ruby
11222 // base container. It should be created or destroyed accordingly.
11223 if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
11224 RubyUtils::IsRubyContainerBox(frameType)) {
11225 // We want to optimize it better, and avoid reframing as much as
11226 // possible. But given the cases above, and the fact that a ruby
11227 // usually won't be very large, it should be fine to reframe it.
11228 TRACE("Ruby");
11229 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11230 return true;
11231 }
11232
11233 // Reframe the multi-column container whenever elements insert/append
11234 // into it because we need to reconstruct column-span split.
11235 if (aFrame->IsColumnSetWrapperFrame()) {
11236 TRACE("Multi-column");
11237 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11238 return true;
11239 }
11240
11241 return false;
11242
11243#undef TRACE
11244}
11245
11246bool nsCSSFrameConstructor::WipeContainingBlock(
11247 nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
11248 nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
11249 nsIFrame* aPrevSibling) {
11250#define TRACE(reason) \
11251 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)
11252 "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)
;
11253
11254 if (aItems.IsEmpty()) {
11255 return false;
11256 }
11257
11258 // Before we go and append the frames, we must check for several
11259 // special situations.
11260
11261 if (aFrame->GetContent() == mDocument->GetRootElement()) {
11262 // Situation #1 is when we insert content that becomes the canonical body
11263 // element, and its used WritingMode is different from the root element's
11264 // used WritingMode.
11265 // We need to reframe the root element so that the root element's frames has
11266 // the correct writing-mode propagated from body element. (See
11267 // nsCSSFrameConstructor::ConstructDocElementFrame.)
11268 //
11269 // Bug 1594297: When inserting a new <body>, we may need to reframe the old
11270 // <body> which has a "overflow" value other than simple "visible". But it's
11271 // tricky, see bug 1593752.
11272 nsIContent* bodyElement = mDocument->GetBodyElement();
11273 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11274 const WritingMode bodyWM(iter.item().mComputedStyle);
11275 if (iter.item().mContent == bodyElement &&
11276 bodyWM != aFrame->GetWritingMode()) {
11277 TRACE("Root");
11278 RecreateFramesForContent(mDocument->GetRootElement(),
11279 InsertionKind::Async);
11280 return true;
11281 }
11282 }
11283 }
11284
11285 nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
11286
11287 // Situation #2 is a flex / grid container frame into which we're inserting
11288 // new inline non-replaced children, adjacent to an existing anonymous flex or
11289 // grid item.
11290 if (aFrame->IsFlexOrGridContainer()) {
11291 FCItemIterator iter(aItems);
11292
11293 // Check if we're adding to-be-wrapped content right *after* an existing
11294 // anonymous flex or grid item (which would need to absorb this content).
11295 const bool isLegacyWebKitBox = IsFlexContainerForLegacyWebKitBox(aFrame);
11296 if (aPrevSibling && IsAnonymousItem(aPrevSibling) &&
11297 iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11298 TRACE("Inserting inline after anon flex or grid item");
11299 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11300 return true;
11301 }
11302
11303 // Check if we're adding to-be-wrapped content right *before* an existing
11304 // anonymous flex or grid item (which would need to absorb this content).
11305 if (nextSibling && IsAnonymousItem(nextSibling)) {
11306 // Jump to the last entry in the list
11307 iter.SetToEnd();
11308 iter.Prev();
11309 if (iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11310 TRACE("Inserting inline before anon flex or grid item");
11311 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11312 return true;
11313 }
11314 }
11315 }
11316
11317 // Situation #3 is an anonymous flex or grid item that's getting new children
11318 // who don't want to be wrapped.
11319 if (IsAnonymousItem(aFrame)) {
11320 AssertAnonymousFlexOrGridItemParent(aFrame, aFrame->GetParent());
11321
11322 // We need to push a null float containing block to be sure that
11323 // "NeedsAnonFlexOrGridItem" will know we're not honoring floats for this
11324 // inserted content. (In particular, this is necessary in order for
11325 // its "GetGeometricParent" call to return the correct result.)
11326 // We're not honoring floats on this content because it has the
11327 // _flex/grid container_ as its parent in the content tree.
11328 nsFrameConstructorSaveState floatSaveState;
11329 aState.PushFloatContainingBlock(nullptr, floatSaveState);
11330
11331 FCItemIterator iter(aItems);
11332 // Skip over things that _do_ need an anonymous flex item, because
11333 // they're perfectly happy to go here -- they won't cause a reframe.
11334 nsIFrame* containerFrame = aFrame->GetParent();
11335 const bool isLegacyWebKitBox =
11336 IsFlexContainerForLegacyWebKitBox(containerFrame);
11337 if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11338 // We hit something that _doesn't_ need an anonymous flex item!
11339 // Rebuild the flex container to bust it out.
11340 TRACE("Inserting non-inlines inside anon flex or grid item");
11341 RecreateFramesForContent(containerFrame->GetContent(),
11342 InsertionKind::Async);
11343 return true;
11344 }
11345
11346 // If we get here, then everything in |aItems| needs to be wrapped in
11347 // an anonymous flex or grid item. That's where it's already going - good!
11348 }
11349
11350 // Situation #4 is a case when table pseudo-frames don't work out right
11351 ParentType parentType = GetParentType(aFrame);
11352 // If all the kids want a parent of the type that aFrame is, then we're all
11353 // set to go. Indeed, there won't be any table pseudo-frames created between
11354 // aFrame and the kids, so those won't need to be merged with any table
11355 // pseudo-frames that might already be kids of aFrame. If aFrame itself is a
11356 // table pseudo-frame, then all the kids in this list would have wanted a
11357 // frame of that type wrapping them anyway, so putting them inside it is ok.
11358 if (!aItems.AllWantParentType(parentType)) {
11359 // Don't give up yet. If parentType is not eTypeBlock and the parent is
11360 // not a generated content frame, then try filtering whitespace out of the
11361 // list.
11362 if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
11363 // For leading whitespace followed by a kid that wants our parent type,
11364 // there are four cases:
11365 // 1) We have a previous sibling which is not a table pseudo. That means
11366 // that previous sibling wanted a (non-block) parent of the type we're
11367 // looking at. Then the whitespace comes between two table-internal
11368 // elements, so should be collapsed out.
11369 // 2) We have a previous sibling which is a table pseudo. It might have
11370 // kids who want this whitespace, so we need to reframe.
11371 // 3) We have no previous sibling and our parent frame is not a table
11372 // pseudo. That means that we'll be at the beginning of our actual
11373 // non-block-type parent, and the whitespace is OK to collapse out.
11374 // If something is ever inserted before us, it'll find our own parent
11375 // as its parent and if it's something that would care about the
11376 // whitespace it'll want a block parent, so it'll trigger a reframe at
11377 // that point.
11378 // 4) We have no previous sibling and our parent frame is a table pseudo.
11379 // Need to reframe.
11380 // All that is predicated on finding the correct previous sibling. We
11381 // might have to walk backwards along continuations from aFrame to do so.
11382 //
11383 // It's always OK to drop whitespace between any two items that want a
11384 // parent of type parentType.
11385 //
11386 // For trailing whitespace preceded by a kid that wants our parent type,
11387 // there are four cases:
11388 // 1) We have a next sibling which is not a table pseudo. That means
11389 // that next sibling wanted a (non-block) parent of the type we're
11390 // looking at. Then the whitespace comes between two table-internal
11391 // elements, so should be collapsed out.
11392 // 2) We have a next sibling which is a table pseudo. It might have
11393 // kids who want this whitespace, so we need to reframe.
11394 // 3) We have no next sibling and our parent frame is not a table
11395 // pseudo. That means that we'll be at the end of our actual
11396 // non-block-type parent, and the whitespace is OK to collapse out.
11397 // If something is ever inserted after us, it'll find our own parent
11398 // as its parent and if it's something that would care about the
11399 // whitespace it'll want a block parent, so it'll trigger a reframe at
11400 // that point.
11401 // 4) We have no next sibling and our parent frame is a table pseudo.
11402 // Need to reframe.
11403 // All that is predicated on finding the correct next sibling. We might
11404 // have to walk forward along continuations from aFrame to do so. That
11405 // said, in the case when nextSibling is null at this point and aIsAppend
11406 // is true, we know we're in case 3. Furthermore, in that case we don't
11407 // even have to worry about the table pseudo situation; we know our
11408 // parent is not a table pseudo there.
11409 FCItemIterator iter(aItems);
11410 FCItemIterator start(iter);
11411 do {
11412 if (iter.SkipItemsWantingParentType(parentType)) {
11413 break;
11414 }
11415
11416 // iter points to an item that wants a different parent. If it's not
11417 // whitespace, we're done; no more point scanning the list.
11418 if (!iter.item().IsWhitespace(aState)) {
11419 break;
11420 }
11421
11422 if (iter == start) {
11423 // Leading whitespace. How to handle this depends on our
11424 // previous sibling and aFrame. See the long comment above.
11425 nsIFrame* prevSibling = aPrevSibling;
11426 if (!prevSibling) {
11427 // Try to find one after all
11428 nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
11429 while (parentPrevCont) {
11430 prevSibling = parentPrevCont->PrincipalChildList().LastChild();
11431 if (prevSibling) {
11432 break;
11433 }
11434 parentPrevCont = parentPrevCont->GetPrevContinuation();
11435 }
11436 };
11437 if (prevSibling) {
11438 if (IsTablePseudo(prevSibling)) {
11439 // need to reframe
11440 break;
11441 }
11442 } else if (IsTablePseudo(aFrame)) {
11443 // need to reframe
11444 break;
11445 }
11446 }
11447
11448 FCItemIterator spaceEndIter(iter);
11449 // Advance spaceEndIter past any whitespace
11450 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
11451
11452 bool okToDrop;
11453 if (trailingSpaces) {
11454 // Trailing whitespace. How to handle this depeds on aIsAppend, our
11455 // next sibling and aFrame. See the long comment above.
11456 okToDrop = aIsAppend && !nextSibling;
11457 if (!okToDrop) {
11458 if (!nextSibling) {
11459 // Try to find one after all
11460 nsIFrame* parentNextCont = aFrame->GetNextContinuation();
11461 while (parentNextCont) {
11462 nextSibling = parentNextCont->PrincipalChildList().FirstChild();
11463 if (nextSibling) {
11464 break;
11465 }
11466 parentNextCont = parentNextCont->GetNextContinuation();
11467 }
11468 }
11469
11470 okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
11471 (!nextSibling && !IsTablePseudo(aFrame));
11472 }
11473#ifdef DEBUG1
11474 else {
11475 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"
, 11475); MOZ_PretendNoReturn(); } } while (0)
;
11476 }
11477#endif
11478 } else {
11479 okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
11480 }
11481
11482 if (okToDrop) {
11483 iter.DeleteItemsTo(this, spaceEndIter);
11484 } else {
11485 // We're done: we don't want to drop the whitespace, and it has the
11486 // wrong parent type.
11487 break;
11488 }
11489
11490 // Now loop, since |iter| points to item right after the whitespace we
11491 // removed.
11492 } while (!iter.IsDone());
11493 }
11494
11495 // We might be able to figure out some sort of optimizations here, but they
11496 // would have to depend on having a correct aPrevSibling and a correct next
11497 // sibling. For example, we can probably avoid reframing if none of
11498 // aFrame, aPrevSibling, and next sibling are table pseudo-frames. But it
11499 // doesn't seem worth it to worry about that for now, especially since we
11500 // in fact do not have a reliable aPrevSibling, nor any next sibling, in
11501 // this method.
11502
11503 // aItems might have changed, so recheck the parent type thing. In fact,
11504 // it might be empty, so recheck that too.
11505 if (aItems.IsEmpty()) {
11506 return false;
11507 }
11508
11509 // If aFrame is empty, the insertion process will be able to take care of
11510 // creating any needed pseudo-parents.
11511 if (!aItems.AllWantParentType(parentType) &&
11512 !SafeToInsertPseudoNeedingChildren(aFrame)) {
11513 // Reframing aFrame->GetContent() is good enough, since the content of
11514 // table pseudo-frames is the ancestor content.
11515 TRACE("Pseudo-frames going wrong");
11516 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11517 return true;
11518 }
11519 }
11520
11521 // Situation #5 is a frame in multicol subtree that's getting new children.
11522 if (aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11523 bool anyColumnSpanItems = false;
11524 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11525 if (iter.item().mComputedStyle->StyleColumn()->IsColumnSpanStyle()) {
11526 anyColumnSpanItems = true;
11527 break;
11528 }
11529 }
11530
11531 bool needsReframe =
11532 // 1. Insert / append any column-span children.
11533 anyColumnSpanItems ||
11534 // 2. GetInsertionPrevSibling() modifies insertion parent. If the prev
11535 // sibling is a column-span, aFrame ends up being the
11536 // column-span-wrapper.
11537 aFrame->Style()->GetPseudoType() ==
11538 PseudoStyleType::columnSpanWrapper ||
11539 // 3. Append into {ib} split container. There might be room for
11540 // optimization, but let's reframe for correctness...
11541 IsFramePartOfIBSplit(aFrame);
11542
11543 if (needsReframe) {
11544 TRACE("Multi-column");
11545 RecreateFramesForContent(
11546 GetMultiColumnContainingBlockFor(aFrame)->GetContent(),
11547 InsertionKind::Async);
11548 return true;
11549 }
11550
11551 // If we get here, then we need further check for {ib} split to decide
11552 // whether to reframe. For example, appending a block into an empty inline
11553 // that is not part of an {ib} split, but should become an {ib} split.
11554 }
11555
11556 // A <fieldset> may need to pick up a new rendered legend from aItems.
11557 // We currently can't handle this case without recreating frames for
11558 // the fieldset.
11559 // XXXmats we should be able to optimize this when the fieldset doesn't
11560 // currently have a rendered legend. ContentRangeInserted needs to be fixed
11561 // to use the inner frame as the content insertion frame in that case.
11562 if (const auto* fieldset = GetFieldSetFrameFor(aFrame)) {
11563 // Check if any item is eligible to be a rendered legend.
11564 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11565 const auto& item = iter.item();
11566 if (!item.mContent->IsHTMLElement(nsGkAtoms::legend)) {
11567 continue;
11568 }
11569 const auto* display = item.mComputedStyle->StyleDisplay();
11570 if (display->IsFloatingStyle() ||
11571 display->IsAbsolutelyPositionedStyle()) {
11572 continue;
11573 }
11574 TRACE("Fieldset with rendered legend");
11575 RecreateFramesForContent(fieldset->GetContent(), InsertionKind::Async);
11576 return true;
11577 }
11578 }
11579
11580 // Now we have several cases involving {ib} splits. Put them all in a
11581 // do/while with breaks to take us to the "go and reconstruct" code.
11582 do {
11583 if (IsInlineFrame(aFrame)) {
11584 if (aItems.AreAllItemsInline()) {
11585 // We can just put the kids in.
11586 return false;
11587 }
11588
11589 if (!IsFramePartOfIBSplit(aFrame)) {
11590 // Need to go ahead and reconstruct.
11591 break;
11592 }
11593
11594 // Now we're adding kids including some blocks to an inline part of an
11595 // {ib} split. If we plan to call AppendFrames, and don't have a next
11596 // sibling for the new frames, and our parent is the last continuation of
11597 // the last part of the {ib} split, and the same is true of all our
11598 // ancestor inlines (they have no following continuations and they're the
11599 // last part of their {ib} splits and we'd be adding to the end for all
11600 // of them), then AppendFrames will handle things for us. Bail out in
11601 // that case.
11602 if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
11603 return false;
11604 }
11605
11606 // Need to reconstruct.
11607 break;
11608 }
11609
11610 // Now we know we have a block parent. If it's not part of an
11611 // ib-split, we're all set.
11612 if (!IsFramePartOfIBSplit(aFrame)) {
11613 return false;
11614 }
11615
11616 // We're adding some kids to a block part of an {ib} split. If all the
11617 // kids are blocks, we don't need to reconstruct.
11618 if (aItems.AreAllItemsBlock()) {
11619 return false;
11620 }
11621
11622 // We might have some inline kids for this block. Just fall out of the
11623 // loop and reconstruct.
11624 } while (false);
11625
11626 // If we don't have a containing block, start with aFrame and look for one.
11627 if (!aContainingBlock) {
11628 aContainingBlock = aFrame;
11629 }
11630
11631 // To find the right block to reframe, just walk up the tree until we find a
11632 // frame that is:
11633 // 1) Not part of an IB split
11634 // 2) Not a pseudo-frame
11635 // 3) Not an inline frame
11636 // We're guaranteed to find one, since ComputedStyle::ApplyStyleFixups
11637 // enforces that the root is display:none, display:table, or display:block.
11638 // Note that walking up "too far" is OK in terms of correctness, even if it
11639 // might be a little inefficient. This is why we walk out of all
11640 // pseudo-frames -- telling which ones are or are not OK to walk out of is
11641 // too hard (and I suspect that we do in fact need to walk out of all of
11642 // them).
11643 while (IsFramePartOfIBSplit(aContainingBlock) ||
11644 aContainingBlock->IsInlineOutside() ||
11645 aContainingBlock->Style()->IsPseudoOrAnonBox()) {
11646 aContainingBlock = aContainingBlock->GetParent();
11647 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"
, 11649); MOZ_PretendNoReturn(); } } while (0)
11648 "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"
, 11649); MOZ_PretendNoReturn(); } } while (0)
11649 "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"
, 11649); MOZ_PretendNoReturn(); } } while (0)
;
11650 }
11651
11652 // Tell parent of the containing block to reformulate the
11653 // entire block. This is painful and definitely not optimal
11654 // but it will *always* get the right answer.
11655
11656 nsIContent* blockContent = aContainingBlock->GetContent();
11657 TRACE("IB splits");
11658 RecreateFramesForContent(blockContent, InsertionKind::Async);
11659 return true;
11660#undef TRACE
11661}
11662
11663void nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame) {
11664 // XXXbz how exactly would we get here while isReflowing anyway? Should this
11665 // whole test be ifdef DEBUG?
11666 if (mPresShell->IsReflowLocked()) {
11667 // don't ReframeContainingBlock, this will result in a crash
11668 // if we remove a tree that's in reflow - see bug 121368 for testcase
11669 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"
, 11671); MOZ_PretendNoReturn(); } while (0)
11670 "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"
, 11671); MOZ_PretendNoReturn(); } while (0)
11671 "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"
, 11671); MOZ_PretendNoReturn(); } while (0)
;
11672 return;
11673 }
11674
11675 // Get the first "normal" ancestor of the target frame.
11676 nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
11677 if (containingBlock) {
11678 // From here we look for the containing block in case the target
11679 // frame is already a block (which can happen when an inline frame
11680 // wraps some of its content in an anonymous block; see
11681 // ConstructInline)
11682
11683 // NOTE: We used to get the FloatContainingBlock here, but it was often
11684 // wrong. GetIBContainingBlock works much better and provides the correct
11685 // container in all cases so GetFloatContainingBlock(aFrame) has been
11686 // removed
11687
11688 // And get the containingBlock's content
11689 if (nsIContent* blockContent = containingBlock->GetContent()) {
11690#ifdef DEBUG1
11691 if (gNoisyContentUpdates) {
11692 printf(" ==> blockContent=%p\n", blockContent);
11693 }
11694#endif
11695 RecreateFramesForContent(blockContent, InsertionKind::Async);
11696 return;
11697 }
11698 }
11699
11700 // If we get here, we're screwed!
11701 RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
11702 InsertionKind::Async);
11703}
11704
11705//////////////////////////////////////////////////////////
11706// nsCSSFrameConstructor::FrameConstructionItem methods //
11707//////////////////////////////////////////////////////////
11708bool nsCSSFrameConstructor::FrameConstructionItem::IsWhitespace(
11709 nsFrameConstructorState& aState) const {
11710 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"
, 11711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11711; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
11711 "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"
, 11711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11711; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11712 if (!mIsText) {
11713 return false;
11714 }
11715 mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
11716 NS_REFRAME_IF_WHITESPACE);
11717 return mContent->TextIsOnlyWhitespace();
11718}
11719
11720//////////////////////////////////////////////////////////////
11721// nsCSSFrameConstructor::FrameConstructionItemList methods //
11722//////////////////////////////////////////////////////////////
11723void nsCSSFrameConstructor::FrameConstructionItemList::AdjustCountsForItem(
11724 FrameConstructionItem* aItem, int32_t aDelta) {
11725 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"
, 11725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDelta == 1 || aDelta == -1"
") (" "Unexpected delta" ")"); do { *((volatile int*)__null)
= 11725; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
11726 mItemCount += aDelta;
11727 if (aItem->mIsAllInline) {
11728 mInlineCount += aDelta;
11729 }
11730 if (aItem->mIsBlock) {
11731 mBlockCount += aDelta;
11732 }
11733 mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
11734}
11735
11736////////////////////////////////////////////////////////////////////////
11737// nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
11738////////////////////////////////////////////////////////////////////////
11739inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11740 SkipItemsWantingParentType(ParentType aParentType) {
11741 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"
, 11741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11741; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11742 while (item().DesiredParentType() == aParentType) {
11743 Next();
11744 if (IsDone()) {
11745 return true;
11746 }
11747 }
11748 return false;
11749}
11750
11751inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11752 SkipItemsNotWantingParentType(ParentType aParentType) {
11753 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"
, 11753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11753; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11754 while (item().DesiredParentType() != aParentType) {
11755 Next();
11756 if (IsDone()) {
11757 return true;
11758 }
11759 }
11760 return false;
11761}
11762
11763// Note: we implement -webkit-{inline-}box using nsFlexContainerFrame, but we
11764// use different rules for what gets wrapped in an anonymous flex item.
11765bool nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem(
11766 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11767 if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) {
11768 // This will be an inline non-replaced box.
11769 return true;
11770 }
11771
11772 if (aIsLegacyWebKitBox) {
11773 if (mComputedStyle->StyleDisplay()->IsInlineOutsideStyle()) {
11774 // In an emulated legacy box, all inline-level content gets wrapped in an
11775 // anonymous flex item.
11776 return true;
11777 }
11778 if (mIsPopup ||
11779 (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
11780 aState.GetGeometricParent(*mComputedStyle->StyleDisplay(), nullptr))) {
11781 // We're abspos or fixedpos (or a XUL popup), which means we'll spawn a
11782 // placeholder which (because our container is an emulated legacy box)
11783 // we'll need to wrap in an anonymous flex item. So, we just treat
11784 // _this_ frame as if _it_ needs to be wrapped in an anonymous flex item,
11785 // and then when we spawn the placeholder, it'll end up in the right
11786 // spot.
11787 return true;
11788 }
11789 }
11790
11791 return false;
11792}
11793
11794inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11795 SkipItemsThatNeedAnonFlexOrGridItem(const nsFrameConstructorState& aState,
11796 bool aIsLegacyWebKitBox) {
11797 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"
, 11797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11797; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11798 while (item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox)) {
11799 Next();
11800 if (IsDone()) {
11801 return true;
11802 }
11803 }
11804 return false;
11805}
11806
11807inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11808 SkipItemsThatDontNeedAnonFlexOrGridItem(
11809 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11810 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"
, 11810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11810; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11811 while (!(item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox))) {
11812 Next();
11813 if (IsDone()) {
11814 return true;
11815 }
11816 }
11817 return false;
11818}
11819
11820inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11821 SkipItemsNotWantingRubyParent() {
11822 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"
, 11822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11822; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11823 while (!IsRubyParentType(item().DesiredParentType())) {
11824 Next();
11825 if (IsDone()) {
11826 return true;
11827 }
11828 }
11829 return false;
11830}
11831
11832inline bool
11833nsCSSFrameConstructor::FrameConstructionItemList::Iterator::SkipWhitespace(
11834 nsFrameConstructorState& aState) {
11835 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"
, 11835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11835; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11836 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"
, 11836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "item().IsWhitespace(aState)"
") (" "Not pointing to whitespace?" ")"); do { *((volatile int
*)__null) = 11836; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11837 do {
11838 Next();
11839 if (IsDone()) {
11840 return true;
11841 }
11842 } while (item().IsWhitespace(aState));
11843
11844 return false;
11845}
11846
11847void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11848 AppendItemToList(FrameConstructionItemList& aTargetList) {
11849 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"
, 11849); MOZ_PretendNoReturn(); } } while (0)
;
11850 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"
, 11850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "should not be done" ")"); do { *((volatile int*)__null
) = 11850; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11851
11852 FrameConstructionItem* item = mCurrent;
11853 Next();
11854 item->remove();
11855 aTargetList.mItems.insertBack(item);
11856
11857 mList.AdjustCountsForItem(item, -1);
11858 aTargetList.AdjustCountsForItem(item, 1);
11859}
11860
11861void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11862 AppendItemsToList(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd,
11863 FrameConstructionItemList& aTargetList) {
11864 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"
, 11864); MOZ_PretendNoReturn(); } } while (0)
;
11865 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"
, 11865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11865; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11866
11867 // We can't just move our guts to the other list if it already has
11868 // some information or if we're not moving our entire list.
11869 if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
11870 do {
11871 AppendItemToList(aTargetList);
11872 } while (*this != aEnd);
11873 return;
11874 }
11875
11876 // Move our entire list of items into the empty target list.
11877 aTargetList.mItems = std::move(mList.mItems);
11878
11879 // Copy over the various counters
11880 aTargetList.mInlineCount = mList.mInlineCount;
11881 aTargetList.mBlockCount = mList.mBlockCount;
11882 aTargetList.mItemCount = mList.mItemCount;
11883 memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
11884 sizeof(aTargetList.mDesiredParentCounts));
11885
11886 // reset mList
11887 mList.Reset(aFCtor);
11888
11889 // Point ourselves to aEnd, as advertised
11890 SetToEnd();
11891 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"
, 11891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this == aEnd"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11891; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11892}
11893
11894void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::InsertItem(
11895 FrameConstructionItem* aItem) {
11896 if (IsDone()) {
11897 mList.mItems.insertBack(aItem);
11898 } else {
11899 // Just insert the item before us. There's no magic here.
11900 mCurrent->setPrevious(aItem);
11901 }
11902 mList.AdjustCountsForItem(aItem, 1);
11903
11904 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"
, 11904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem->getNext() == mCurrent"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11904; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11905}
11906
11907void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::DeleteItemsTo(
11908 nsCSSFrameConstructor* aFCtor, const Iterator& aEnd) {
11909 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"
, 11909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11909; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11910 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"
, 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this != aEnd"
") (" "Shouldn't be at aEnd yet" ")"); do { *((volatile int*
)__null) = 11910; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11911
11912 do {
11913 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"
, 11913); MOZ_PretendNoReturn(); } } while (0)
;
11914 FrameConstructionItem* item = mCurrent;
11915 Next();
11916 item->remove();
11917 mList.AdjustCountsForItem(item, -1);
11918 item->Delete(aFCtor);
11919 } while (*this != aEnd);
11920}
11921
11922void nsCSSFrameConstructor::QuotesDirty() {
11923 mQuotesDirty = true;
11924 mPresShell->SetNeedLayoutFlush();
11925}
11926
11927void nsCSSFrameConstructor::CountersDirty() {
11928 mCountersDirty = true;
11929 mPresShell->SetNeedLayoutFlush();
11930}
11931
11932void* nsCSSFrameConstructor::AllocateFCItem() {
11933 void* item;
11934 if (mFirstFreeFCItem) {
11935 item = mFirstFreeFCItem;
11936 mFirstFreeFCItem = mFirstFreeFCItem->mNext;
11937 } else {
11938 item = mFCItemPool.Allocate(sizeof(FrameConstructionItem));
11939 }
11940 ++mFCItemsInUse;
11941 return item;
11942}
11943
11944void nsCSSFrameConstructor::FreeFCItem(FrameConstructionItem* aItem) {
11945 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"
, 11945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFCItemsInUse != 0"
")"); do { *((volatile int*)__null) = 11945; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11946 if (--mFCItemsInUse == 0) {
11947 // The arena is now unused - clear it but retain one chunk.
11948 mFirstFreeFCItem = nullptr;
11949 mFCItemPool.Clear();
11950 } else {
11951 // Prepend it to the list of free items.
11952 FreeFCItemLink* item = reinterpret_cast<FreeFCItemLink*>(aItem);
11953 item->mNext = mFirstFreeFCItem;
11954 mFirstFreeFCItem = item;
11955 }
11956}
11957
11958void nsCSSFrameConstructor::AddSizeOfIncludingThis(
11959 nsWindowSizes& aSizes) const {
11960 if (nsIFrame* rootFrame = GetRootFrame()) {
11961 rootFrame->AddSizeOfExcludingThisForTree(aSizes);
11962 if (RetainedDisplayListBuilder* builder =
11963 rootFrame->GetProperty(RetainedDisplayListBuilder::Cached())) {
11964 builder->AddSizeOfIncludingThis(aSizes);
11965 }
11966 }
11967
11968 // This must be done after measuring from the frame tree, since frame
11969 // manager will measure sizes of staled computed values and style
11970 // structs, which only make sense after we know what are being used.
11971 nsFrameManager::AddSizeOfIncludingThis(aSizes);
11972
11973 // Measurement of the following members may be added later if DMD finds it
11974 // is worthwhile:
11975 // - mFCItemPool
11976 // - mContainStyleScopeManager
11977}