Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp
Warning:line 7508, 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-18/lib/clang/18 -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-18/lib/clang/18/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 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -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-07-30-004816-4182763-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
2691 Print presentation, non-XUL
2692
2693 ViewportFrame
2694 nsCanvasFrame
2695 nsPageSequenceFrame
2696 PrintedSheetFrame
2697 nsPageFrame
2698 nsPageContentFrame [fixed-cb]
2699 nsCanvasFrame [abs-cb]
2700 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2701 nsTableWrapperFrame, nsPlaceholderFrame)
2702
2703 Print-preview presentation, non-XUL
2704
2705 ViewportFrame
2706 ScrollContainerFrame
2707 nsCanvasFrame
2708 nsPageSequenceFrame
2709 PrintedSheetFrame
2710 nsPageFrame
2711 nsPageContentFrame [fixed-cb]
2712 nsCanvasFrame [abs-cb]
2713 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2714 nsTableWrapperFrame,
2715 nsPlaceholderFrame)
2716
2717 Print/print preview of XUL is not supported.
2718 [fixed-cb]: the default containing block for fixed-pos content
2719 [abs-cb]: the default containing block for abs-pos content
2720
2721 Meaning of nsCSSFrameConstructor fields:
2722 mRootElementFrame is "root element frame". This is the primary frame for
2723 the root element.
2724 mDocElementContainingBlock is the parent of mRootElementFrame
2725 (i.e. nsCanvasFrame)
2726 mPageSequenceFrame is the nsPageSequenceFrame, or null if there isn't
2727 one
2728 */
2729
2730 // --------- CREATE ROOT FRAME -------
2731
2732 // Create the root frame. The document element's frame is a child of the
2733 // root frame.
2734 //
2735 // The root frame serves two purposes:
2736 // - reserves space for any margins needed for the document element's frame
2737 // - renders the document element's background. This ensures the background
2738 // covers the entire canvas as specified by the CSS2 spec
2739
2740 nsPresContext* presContext = mPresShell->GetPresContext();
2741 const bool isPaginated = presContext->IsRootPaginatedDocument();
2742
2743 const bool isHTML = aDocElement->IsHTMLElement();
2744 const bool isXUL = !isHTML && aDocElement->IsXULElement();
2745
2746 const bool isScrollable = [&] {
2747 if (isPaginated) {
2748 return presContext->HasPaginatedScrolling();
2749 }
2750 // Never create scrollbars for XUL documents or top level XHTML documents
2751 // that disable scrolling.
2752 if (isXUL) {
2753 return false;
2754 }
2755 if (aDocElement->OwnerDoc()->ChromeRulesEnabled() &&
2756 aDocElement->AsElement()->AttrValueIs(
2757 kNameSpaceID_None, nsGkAtoms::scrolling, nsGkAtoms::_false,
2758 eCaseMatters)) {
2759 return false;
2760 }
2761 return true;
2762 }();
2763
2764 nsContainerFrame* viewportFrame =
2765 static_cast<nsContainerFrame*>(GetRootFrame());
2766 ComputedStyle* viewportPseudoStyle = viewportFrame->Style();
2767
2768 nsCanvasFrame* rootCanvasFrame =
2769 NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
2770 PseudoStyleType rootPseudo = PseudoStyleType::canvas;
2771 mCanvasFrame = rootCanvasFrame;
2772 mDocElementContainingBlock = rootCanvasFrame;
2773
2774 // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
2775
2776 // If the device supports scrolling (e.g., in galley mode on the screen and
2777 // for print-preview, but not when printing), then create a scroll frame that
2778 // will act as the scrolling mechanism for the viewport.
2779 // XXX Do we even need a viewport when printing to a printer?
2780
2781 // We no longer need to do overflow propagation here. It's taken care of
2782 // when we construct frames for the element whose overflow might be
2783 // propagated
2784 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"
, 2785); MOZ_PretendNoReturn(); } } while (0)
2785 "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"
, 2785); MOZ_PretendNoReturn(); } } while (0)
;
2786
2787 nsContainerFrame* newFrame = rootCanvasFrame;
2788 RefPtr<ComputedStyle> rootPseudoStyle;
2789 // we must create a state because if the scrollbars are GFX it needs the
2790 // state to build the scrollbar frames.
2791 nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
2792
2793 // Start off with the viewport as parent; we'll adjust it as needed.
2794 nsContainerFrame* parentFrame = viewportFrame;
2795
2796 ServoStyleSet* styleSet = mPresShell->StyleSet();
2797 // If paginated, make sure we don't put scrollbars in
2798 if (!isScrollable) {
2799 rootPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
2800 rootPseudo, viewportPseudoStyle);
2801 } else {
2802 rootPseudo = PseudoStyleType::scrolledCanvas;
2803
2804 // Build the frame. We give it the content we are wrapping which is the
2805 // document element, the root frame, the parent view port frame, and we
2806 // should get back the new frame and the scrollable view if one was
2807 // created.
2808
2809 // resolve a context for the scrollframe
2810 RefPtr<ComputedStyle> computedStyle =
2811 styleSet->ResolveInheritingAnonymousBoxStyle(
2812 PseudoStyleType::viewportScroll, viewportPseudoStyle);
2813
2814 // Note that the viewport scrollframe is always built with
2815 // overflow:auto style. This forces the scroll frame to create
2816 // anonymous content for both scrollbars. This is necessary even
2817 // if the HTML or BODY elements are overriding the viewport
2818 // scroll style to 'hidden' --- dynamic style changes might put
2819 // scrollbars back on the viewport and we don't want to have to
2820 // reframe the viewport to create the scrollbar content.
2821 newFrame = nullptr;
2822 rootPseudoStyle = BeginBuildingScrollContainerFrame(
2823 state, aDocElement, computedStyle, viewportFrame, rootPseudo, true,
2824 newFrame);
2825 parentFrame = newFrame;
2826 }
2827
2828 rootCanvasFrame->SetComputedStyleWithoutNotification(rootPseudoStyle);
2829 rootCanvasFrame->Init(aDocElement, parentFrame, nullptr);
2830
2831 if (isScrollable) {
2832 FinishBuildingScrollContainerFrame(parentFrame, rootCanvasFrame);
2833 }
2834
2835 if (isPaginated) {
2836 // Create a page sequence frame
2837 {
2838 RefPtr<ComputedStyle> pageSequenceStyle =
2839 styleSet->ResolveInheritingAnonymousBoxStyle(
2840 PseudoStyleType::pageSequence, viewportPseudoStyle);
2841 mPageSequenceFrame =
2842 NS_NewPageSequenceFrame(mPresShell, pageSequenceStyle);
2843 mPageSequenceFrame->Init(aDocElement, rootCanvasFrame, nullptr);
2844 SetInitialSingleChild(rootCanvasFrame, mPageSequenceFrame);
2845 }
2846
2847 // Create the first printed sheet frame, as the sole child (for now) of our
2848 // page sequence frame (mPageSequenceFrame).
2849 auto* printedSheetFrame =
2850 ConstructPrintedSheetFrame(mPresShell, mPageSequenceFrame, nullptr);
2851 SetInitialSingleChild(mPageSequenceFrame, printedSheetFrame);
2852
2853 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"
, 2854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2854; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2854 "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"
, 2854); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2854; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2855
2856 // Create the first page, as the sole child (for now) of the printed sheet
2857 // frame that we just created.
2858 nsCanvasFrame* canvasFrame;
2859 nsContainerFrame* pageFrame =
2860 ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
2861 pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2862 SetInitialSingleChild(printedSheetFrame, pageFrame);
2863
2864 // The eventual parent of the document element frame.
2865 // XXX should this be set for every new page (in ConstructPageFrame)?
2866 mDocElementContainingBlock = canvasFrame;
2867 }
2868
2869 if (viewportFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
2870 SetInitialSingleChild(viewportFrame, newFrame);
2871 } else {
2872 viewportFrame->AppendFrames(FrameChildListID::Principal,
2873 nsFrameList(newFrame, newFrame));
2874 }
2875}
2876
2877void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
2878 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
2879 nsIContent* aDocElement, nsFrameList& aFrameList) {
2880 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"
, 2880); MOZ_PretendNoReturn(); } } while (0)
;
2881 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"
, 2881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRootElementFrame->GetContent() == aDocElement"
")"); do { *((volatile int*)__null) = 2881; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2882
2883 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
2884 GetAnonymousContent(aDocElement, aFrame, anonymousItems);
2885 if (anonymousItems.IsEmpty()) {
2886 return;
2887 }
2888
2889 AutoFrameConstructionItemList itemsToConstruct(this);
2890 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
2891 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
2892 itemsToConstruct, pageNameTracker);
2893 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
2894 /* aParentIsWrapperAnonBox = */ false,
2895 aFrameList);
2896}
2897
2898PrintedSheetFrame* nsCSSFrameConstructor::ConstructPrintedSheetFrame(
2899 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2900 nsIFrame* aPrevSheetFrame) {
2901 RefPtr<ComputedStyle> printedSheetPseudoStyle =
2902 aPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
2903 PseudoStyleType::printedSheet);
2904
2905 auto* printedSheetFrame =
2906 NS_NewPrintedSheetFrame(aPresShell, printedSheetPseudoStyle);
2907
2908 printedSheetFrame->Init(nullptr, aParentFrame, aPrevSheetFrame);
2909
2910 return printedSheetFrame;
2911}
2912
2913nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
2914 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2915 nsIFrame* aPrevPageFrame, nsCanvasFrame*& aCanvasFrame) {
2916 ServoStyleSet* styleSet = aPresShell->StyleSet();
2917
2918 RefPtr<ComputedStyle> pagePseudoStyle =
2919 styleSet->ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType::page);
2920
2921 nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
2922
2923 // Initialize the page frame and force it to have a view. This makes printing
2924 // of the pages easier and faster.
2925 pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
2926
2927 RefPtr<const nsAtom> pageName;
2928 if (mNextPageContentFramePageName) {
2929 pageName = mNextPageContentFramePageName.forget();
2930 } else if (aPrevPageFrame) {
2931 pageName = aPrevPageFrame->ComputePageValue();
2932 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"
, 2933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2933 "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"
, 2933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2934 }
2935 RefPtr<ComputedStyle> pageContentPseudoStyle =
2936 styleSet->ResolvePageContentStyle(pageName,
2937 StylePagePseudoClassFlags::NONE);
2938
2939 nsContainerFrame* pageContentFrame = NS_NewPageContentFrame(
2940 aPresShell, pageContentPseudoStyle, pageName.forget());
2941
2942 nsPageContentFrame* prevPageContentFrame = nullptr;
2943 if (aPrevPageFrame) {
2944 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"
, 2944); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevPageFrame->IsPageFrame()"
")"); do { *((volatile int*)__null) = 2944; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2945 prevPageContentFrame =
2946 static_cast<nsPageFrame*>(aPrevPageFrame)->PageContentFrame();
2947 }
2948 pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
2949 if (!prevPageContentFrame) {
2950 // The canvas is an inheriting anon box, so needs to be "owned" by the page
2951 // content.
2952 pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2953 }
2954 SetInitialSingleChild(pageFrame, pageContentFrame);
2955 // Make it an absolute container for fixed-pos elements
2956 pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2957 pageContentFrame->MarkAsAbsoluteContainingBlock();
2958
2959 RefPtr<ComputedStyle> canvasPseudoStyle =
2960 styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::canvas,
2961 pageContentPseudoStyle);
2962
2963 aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
2964
2965 nsIFrame* prevCanvasFrame = nullptr;
2966 if (prevPageContentFrame) {
2967 prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
2968 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"
, 2968); MOZ_PretendNoReturn(); } } while (0)
;
2969 }
2970 aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
2971 SetInitialSingleChild(pageContentFrame, aCanvasFrame);
2972 return pageFrame;
2973}
2974
2975/* static */
2976nsIFrame* nsCSSFrameConstructor::CreatePlaceholderFrameFor(
2977 PresShell* aPresShell, nsIContent* aContent, nsIFrame* aFrame,
2978 nsContainerFrame* aParentFrame, nsIFrame* aPrevInFlow,
2979 nsFrameState aTypeBit) {
2980 RefPtr<ComputedStyle> placeholderStyle =
2981 aPresShell->StyleSet()->ResolveStyleForPlaceholder();
2982
2983 // The placeholder frame gets a pseudo style.
2984 nsPlaceholderFrame* placeholderFrame =
2985 NS_NewPlaceholderFrame(aPresShell, placeholderStyle, aTypeBit);
2986
2987 placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
2988
2989 // Associate the placeholder/out-of-flow with each other.
2990 placeholderFrame->SetOutOfFlowFrame(aFrame);
2991 aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame);
2992
2993 aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
2994
2995 return placeholderFrame;
2996}
2997
2998// Clears any lazy bits set in the range [aStartContent, aEndContent). If
2999// aEndContent is null, that means to clear bits in all siblings starting with
3000// aStartContent. aStartContent must not be null unless aEndContent is also
3001// null. We do this so that when new children are inserted under elements whose
3002// frame is a leaf the new children don't cause us to try to construct frames
3003// for the existing children again.
3004static inline void ClearLazyBits(nsIContent* aStartContent,
3005 nsIContent* aEndContent) {
3006 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"
, 3007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3007; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3007 "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"
, 3007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3007; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3008
3009 for (nsIContent* cur = aStartContent; cur != aEndContent;
3010 cur = cur->GetNextSibling()) {
3011 cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
3012 }
3013}
3014
3015/* static */
3016const nsCSSFrameConstructor::FrameConstructionData*
3017nsCSSFrameConstructor::FindSelectData(const Element& aElement,
3018 ComputedStyle& aStyle) {
3019 // Construct a frame-based listbox or combobox
3020 const auto* sel = dom::HTMLSelectElement::FromNode(aElement);
3021 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"
, 3021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sel" ")"); do
{ *((volatile int*)__null) = 3021; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3022 if (sel->IsCombobox()) {
3023 static constexpr FrameConstructionData sComboboxData{
3024 ToCreationFunc(NS_NewComboboxControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewComboboxControlFrame(aPs, aStyle); }
, 0,
3025 PseudoStyleType::buttonContent};
3026 return &sComboboxData;
3027 }
3028 // FIXME: Can we simplify this to avoid needing ConstructListboxSelectFrame,
3029 // and reuse ConstructScrollableBlock or so?
3030 static constexpr FrameConstructionData sListBoxData{
3031 &nsCSSFrameConstructor::ConstructListBoxSelectFrame};
3032 return &sListBoxData;
3033}
3034
3035nsIFrame* nsCSSFrameConstructor::ConstructListBoxSelectFrame(
3036 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3037 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3038 nsFrameList& aFrameList) {
3039 nsIContent* const content = aItem.mContent;
3040 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3041
3042 // Listbox, not combobox
3043 nsContainerFrame* listFrame =
3044 NS_NewListControlFrame(mPresShell, computedStyle);
3045
3046 nsContainerFrame* scrolledFrame =
3047 NS_NewSelectsAreaFrame(mPresShell, computedStyle);
3048
3049 // ******* this code stolen from Initialze ScrollFrame ********
3050 // please adjust this code to use BuildScrollFrame.
3051
3052 InitializeListboxSelect(aState, listFrame, scrolledFrame, content,
3053 aParentFrame, computedStyle, aFrameList);
3054
3055 return listFrame;
3056}
3057
3058void nsCSSFrameConstructor::InitializeListboxSelect(
3059 nsFrameConstructorState& aState, nsContainerFrame* scrollFrame,
3060 nsContainerFrame* scrolledFrame, nsIContent* aContent,
3061 nsContainerFrame* aParentFrame, ComputedStyle* aComputedStyle,
3062 nsFrameList& aFrameList) {
3063 // Initialize it
3064 nsContainerFrame* geometricParent =
3065 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
3066
3067 // We don't call InitAndRestoreFrame for scrollFrame because we can only
3068 // restore the frame state after its parts have been created (in particular,
3069 // the scrollable view). So we have to split Init and Restore.
3070
3071 scrollFrame->Init(aContent, geometricParent, nullptr);
3072 aState.AddChild(scrollFrame, aFrameList, aContent, aParentFrame);
3073 BuildScrollContainerFrame(aState, aContent, aComputedStyle, scrolledFrame,
3074 geometricParent, scrollFrame);
3075 if (aState.mFrameState) {
3076 // Restore frame state for the scroll frame
3077 RestoreFrameStateFor(scrollFrame, aState.mFrameState);
3078 }
3079
3080 nsFrameConstructorSaveState floatSaveState;
3081 aState.MaybePushFloatContainingBlock(scrolledFrame, floatSaveState);
3082
3083 // Process children
3084 nsFrameList childList;
3085
3086 ProcessChildren(aState, aContent, aComputedStyle, scrolledFrame, false,
3087 childList, false);
3088
3089 // Set the scrolled frame's initial child lists
3090 scrolledFrame->SetInitialChildList(FrameChildListID::Principal,
3091 std::move(childList));
3092}
3093
3094nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
3095 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3096 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3097 nsFrameList& aFrameList) {
3098 AutoRestore<bool> savedHasRenderedLegend(aState.mHasRenderedLegend);
3099 aState.mHasRenderedLegend = false;
3100 nsIContent* const content = aItem.mContent;
3101 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3102
3103 nsContainerFrame* fieldsetFrame =
3104 NS_NewFieldSetFrame(mPresShell, computedStyle);
3105
3106 // Initialize it
3107 InitAndRestoreFrame(aState, content,
3108 aState.GetGeometricParent(*aStyleDisplay, aParentFrame),
3109 fieldsetFrame);
3110
3111 fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3112
3113 // Resolve style and initialize the frame
3114 RefPtr<ComputedStyle> fieldsetContentStyle =
3115 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3116 PseudoStyleType::fieldsetContent, computedStyle);
3117
3118 const nsStyleDisplay* fieldsetContentDisplay =
3119 fieldsetContentStyle->StyleDisplay();
3120 const bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
3121 nsContainerFrame* scrollFrame = nullptr;
3122 if (isScrollable) {
3123 fieldsetContentStyle = BeginBuildingScrollContainerFrame(
3124 aState, content, fieldsetContentStyle, fieldsetFrame,
3125 PseudoStyleType::scrolledContent, false, scrollFrame);
3126 }
3127
3128 // Create the inner ::-moz-fieldset-content frame.
3129 nsContainerFrame* contentFrameTop;
3130 nsContainerFrame* contentFrame;
3131 auto* parent = scrollFrame ? scrollFrame : fieldsetFrame;
3132 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"
, 3133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3133 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"
, 3133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3134 switch (fieldsetContentDisplay->DisplayInside()) {
3135 case StyleDisplayInside::Flex:
3136 contentFrame = NS_NewFlexContainerFrame(mPresShell, fieldsetContentStyle);
3137 InitAndRestoreFrame(aState, content, parent, contentFrame);
3138 contentFrameTop = contentFrame;
3139 break;
3140 case StyleDisplayInside::Grid:
3141 contentFrame = NS_NewGridContainerFrame(mPresShell, fieldsetContentStyle);
3142 InitAndRestoreFrame(aState, content, parent, contentFrame);
3143 contentFrameTop = contentFrame;
3144 break;
3145 default: {
3146 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"
, 3147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3147; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3147 "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"
, 3147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3147; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3148
3149 contentFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle);
3150 if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
3151 contentFrameTop = BeginBuildingColumns(
3152 aState, content, parent, contentFrame, fieldsetContentStyle);
3153 } else {
3154 // No need to create column container. Initialize content frame.
3155 InitAndRestoreFrame(aState, content, parent, contentFrame);
3156 contentFrameTop = contentFrame;
3157 }
3158
3159 break;
3160 }
3161 }
3162
3163 aState.AddChild(fieldsetFrame, aFrameList, content, aParentFrame);
3164
3165 // Process children
3166 nsFrameConstructorSaveState absoluteSaveState;
3167 nsFrameList childList;
3168
3169 contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3170 if (fieldsetFrame->IsAbsPosContainingBlock()) {
3171 aState.PushAbsoluteContainingBlock(contentFrameTop, fieldsetFrame,
3172 absoluteSaveState);
3173 }
3174
3175 nsFrameConstructorSaveState floatSaveState;
3176 aState.MaybePushFloatContainingBlock(contentFrame, floatSaveState);
3177
3178 ProcessChildren(aState, content, computedStyle, contentFrame, true, childList,
3179 true);
3180 nsFrameList fieldsetKids;
3181 fieldsetKids.AppendFrame(nullptr,
3182 scrollFrame ? scrollFrame : contentFrameTop);
3183
3184 if (!MayNeedToCreateColumnSpanSiblings(contentFrame, childList)) {
3185 // Set the inner frame's initial child lists.
3186 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3187 std::move(childList));
3188 } else {
3189 // Extract any initial non-column-span kids, and put them in inner frame's
3190 // child list.
3191 nsFrameList initialNonColumnSpanKids =
3192 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3193 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3194 std::move(initialNonColumnSpanKids));
3195
3196 if (childList.NotEmpty()) {
3197 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3198 aState, contentFrame, childList,
3199 // Column content should never be a absolute/fixed positioned
3200 // containing block. Pass nullptr as aPositionedFrame.
3201 nullptr);
3202 FinishBuildingColumns(aState, contentFrameTop, contentFrame,
3203 columnSpanSiblings);
3204 }
3205 }
3206
3207 if (isScrollable) {
3208 FinishBuildingScrollContainerFrame(scrollFrame, contentFrameTop);
3209 }
3210
3211 // We use AppendFrames here because the rendered legend will already
3212 // be present in the principal child list if it exists.
3213 fieldsetFrame->AppendFrames(FrameChildListID::NoReflowPrincipal,
3214 std::move(fieldsetKids));
3215
3216 return fieldsetFrame;
3217}
3218
3219const nsCSSFrameConstructor::FrameConstructionData*
3220nsCSSFrameConstructor::FindDetailsData(const Element& aElement,
3221 ComputedStyle& aStyle) {
3222 if (!StaticPrefs::layout_details_force_block_layout()) {
3223 return nullptr;
3224 }
3225 static constexpr FrameConstructionData sBlockData[2] = {
3226 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
3227 {&nsCSSFrameConstructor::ConstructScrollableBlock},
3228 };
3229 return &sBlockData[aStyle.StyleDisplay()->IsScrollableOverflow()];
3230}
3231
3232nsIFrame* nsCSSFrameConstructor::ConstructBlockRubyFrame(
3233 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3234 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3235 nsFrameList& aFrameList) {
3236 nsIContent* const content = aItem.mContent;
3237 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3238
3239 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, computedStyle);
3240 nsContainerFrame* newFrame = blockFrame;
3241 nsContainerFrame* geometricParent =
3242 aState.GetGeometricParent(*aStyleDisplay, aParentFrame);
3243 AutoFrameConstructionPageName pageNameTracker(aState, blockFrame);
3244 if ((aItem.mFCData->mBits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3245 aStyleDisplay->IsScrollableOverflow()) {
3246 nsContainerFrame* scrollframe = nullptr;
3247 BuildScrollContainerFrame(aState, content, computedStyle, blockFrame,
3248 geometricParent, scrollframe);
3249 newFrame = scrollframe;
3250 } else {
3251 InitAndRestoreFrame(aState, content, geometricParent, blockFrame);
3252 }
3253
3254 RefPtr<ComputedStyle> rubyStyle =
3255 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3256 PseudoStyleType::blockRubyContent, computedStyle);
3257 nsContainerFrame* rubyFrame = NS_NewRubyFrame(mPresShell, rubyStyle);
3258 InitAndRestoreFrame(aState, content, blockFrame, rubyFrame);
3259 SetInitialSingleChild(blockFrame, rubyFrame);
3260 blockFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3261
3262 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
3263
3264 if (!mRootElementFrame) {
3265 mRootElementFrame = newFrame;
3266 }
3267
3268 nsFrameConstructorSaveState absoluteSaveState;
3269 blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3270 if (newFrame->IsAbsPosContainingBlock()) {
3271 aState.PushAbsoluteContainingBlock(blockFrame, blockFrame,
3272 absoluteSaveState);
3273 }
3274 nsFrameConstructorSaveState floatSaveState;
3275 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
3276
3277 nsFrameList childList;
3278 ProcessChildren(aState, content, rubyStyle, rubyFrame, true, childList, false,
3279 nullptr);
3280 rubyFrame->SetInitialChildList(FrameChildListID::Principal,
3281 std::move(childList));
3282
3283 return newFrame;
3284}
3285
3286static nsIFrame* FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame) {
3287 for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
3288 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"
, 3289); MOZ_PretendNoReturn(); } } while (0)
3289 "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"
, 3289); MOZ_PretendNoReturn(); } } while (0)
;
3290 auto pseudo = f->Style()->GetPseudoType();
3291 if (pseudo == PseudoStyleType::before || pseudo == PseudoStyleType::after ||
3292 pseudo == PseudoStyleType::marker)
3293 return f;
3294 }
3295 return nullptr;
3296}
3297
3298/* static */
3299const nsCSSFrameConstructor::FrameConstructionData*
3300nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
3301 nsIFrame* aParentFrame) {
3302 if (aParentFrame && IsFrameForSVG(aParentFrame)) {
3303 if (!aParentFrame->IsInSVGTextSubtree()) {
3304 return nullptr;
3305 }
3306
3307 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
3308 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
3309 // really know how to deal with it. This kinda sucks. :(
3310 if (aParentFrame->GetContent() != aTextContent.GetParent()) {
3311 return nullptr;
3312 }
3313
3314 static constexpr FrameConstructionData sSVGTextData(
3315 NS_NewTextFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_SVG_TEXT0x80000);
3316 return &sSVGTextData;
3317 }
3318
3319 static constexpr FrameConstructionData sTextData(NS_NewTextFrame,
3320 FCDATA_IS_LINE_PARTICIPANT0x2000);
3321 return &sTextData;
3322}
3323
3324void nsCSSFrameConstructor::ConstructTextFrame(
3325 const FrameConstructionData* aData, nsFrameConstructorState& aState,
3326 nsIContent* aContent, nsContainerFrame* aParentFrame,
3327 ComputedStyle* aComputedStyle, nsFrameList& aFrameList) {
3328 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"
, 3328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aData" ") ("
"Must have frame construction data" ")"); do { *((volatile int
*)__null) = 3328; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3329
3330 nsIFrame* newFrame =
3331 (*aData->mFunc.mCreationFunc)(mPresShell, aComputedStyle);
3332
3333 InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
3334
3335 // We never need to create a view for a text frame.
3336
3337 if (newFrame->IsGeneratedContentFrame()) {
3338 UniquePtr<nsGenConInitializer> initializer(
3339 static_cast<nsGenConInitializer*>(
3340 aContent->TakeProperty(nsGkAtoms::genConInitializerProperty)));
3341 if (initializer) {
3342 if (initializer->mNode.release()->InitTextFrame(
3343 initializer->mList,
3344 FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
3345 (this->*(initializer->mDirtyAll))();
3346 }
3347 }
3348 }
3349
3350 // Add the newly constructed frame to the flow
3351 aFrameList.AppendFrame(nullptr, newFrame);
3352
3353 if (!aState.mCreatingExtraFrames || (aContent->IsInNativeAnonymousSubtree() &&
3354 !aContent->GetPrimaryFrame())) {
3355 aContent->SetPrimaryFrame(newFrame);
3356 }
3357}
3358
3359/* static */
3360const nsCSSFrameConstructor::FrameConstructionData*
3361nsCSSFrameConstructor::FindDataByInt(int32_t aInt, const Element& aElement,
3362 ComputedStyle& aComputedStyle,
3363 const FrameConstructionDataByInt* aDataPtr,
3364 uint32_t aDataLength) {
3365 for (const FrameConstructionDataByInt *curData = aDataPtr,
3366 *endData = aDataPtr + aDataLength;
3367 curData != endData; ++curData) {
3368 if (curData->mInt == aInt) {
3369 const FrameConstructionData* data = &curData->mData;
3370 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3371 return data->mFunc.mDataGetter(aElement, aComputedStyle);
3372 }
3373
3374 return data;
3375 }
3376 }
3377
3378 return nullptr;
3379}
3380
3381/* static */
3382const nsCSSFrameConstructor::FrameConstructionData*
3383nsCSSFrameConstructor::FindDataByTag(const Element& aElement,
3384 ComputedStyle& aStyle,
3385 const FrameConstructionDataByTag* aDataPtr,
3386 uint32_t aDataLength) {
3387 const nsAtom* tag = aElement.NodeInfo()->NameAtom();
3388 for (const FrameConstructionDataByTag *curData = aDataPtr,
3389 *endData = aDataPtr + aDataLength;
3390 curData != endData; ++curData) {
3391 if (curData->mTag == tag) {
3392 const FrameConstructionData* data = &curData->mData;
3393 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3394 return data->mFunc.mDataGetter(aElement, aStyle);
3395 }
3396
3397 return data;
3398 }
3399 }
3400
3401 return nullptr;
3402}
3403
3404#define SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40) FrameConstructionData(nullptr, FCDATA_SUPPRESS_FRAME0x40)
3405#define SIMPLE_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3406 {int32_t(_int), FrameConstructionData(_func)}
3407#define SIMPLE_INT_CHAIN(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3408 {int32_t(_int), FrameConstructionData(_func)}
3409#define COMPLEX_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3410 {int32_t(_int), FrameConstructionData(_func)}
3411
3412#define SIMPLE_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3413 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3414#define SIMPLE_TAG_CHAIN(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3415 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3416#define COMPLEX_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3417 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3418
3419static nsFieldSetFrame* GetFieldSetFrameFor(nsIFrame* aFrame) {
3420 auto pseudo = aFrame->Style()->GetPseudoType();
3421 if (pseudo == PseudoStyleType::fieldsetContent ||
3422 pseudo == PseudoStyleType::scrolledContent ||
3423 pseudo == PseudoStyleType::columnSet ||
3424 pseudo == PseudoStyleType::columnContent) {
3425 return GetFieldSetFrameFor(aFrame->GetParent());
3426 }
3427 return do_QueryFrame(aFrame);
3428}
3429
3430/* static */
3431const nsCSSFrameConstructor::FrameConstructionData*
3432nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
3433 nsIFrame* aParentFrame,
3434 ComputedStyle& aStyle) {
3435 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"
, 3435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsHTMLElement()"
")"); do { *((volatile int*)__null) = 3435; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3436 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"
, 3440); MOZ_PretendNoReturn(); } } while (0)
3437 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"
, 3440); MOZ_PretendNoReturn(); } } while (0)
3438 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"
, 3440); MOZ_PretendNoReturn(); } } while (0)
3439 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"
, 3440); MOZ_PretendNoReturn(); } } while (0)
3440 "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"
, 3440); MOZ_PretendNoReturn(); } } while (0)
;
3441
3442 if (aElement.IsInNativeAnonymousSubtree() &&
3443 aElement.NodeInfo()->NameAtom() == nsGkAtoms::label && aParentFrame) {
3444 if (aParentFrame->IsFileControlFrame()) {
3445 static constexpr FrameConstructionData sFileLabelData(
3446 NS_NewFileControlLabelFrame);
3447 return &sFileLabelData;
3448 }
3449 if (aParentFrame->GetParent() &&
3450 aParentFrame->GetParent()->IsComboboxControlFrame()) {
3451 static constexpr FrameConstructionData sComboboxLabelData(
3452 NS_NewComboboxLabelFrame);
3453 return &sComboboxLabelData;
3454 }
3455 }
3456
3457 static constexpr FrameConstructionDataByTag sHTMLData[] = {
3458 SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData){nsGkAtoms::img, FrameConstructionData(nsCSSFrameConstructor::
FindImgData)}
,
3459 SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,{nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
3460 nsCSSFrameConstructor::FindGeneratedImageData){nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
,
3461 {nsGkAtoms::br,
3462 {NS_NewBRFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_LINE_BREAK0x4000}},
3463 SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame){nsGkAtoms::wbr, FrameConstructionData(NS_NewWBRFrame)},
3464 SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData){nsGkAtoms::input, FrameConstructionData(nsCSSFrameConstructor
::FindInputData)}
,
3465 SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame){nsGkAtoms::textarea, FrameConstructionData(NS_NewTextControlFrame
)}
,
3466 SIMPLE_TAG_CHAIN(select, nsCSSFrameConstructor::FindSelectData){nsGkAtoms::select, FrameConstructionData(nsCSSFrameConstructor
::FindSelectData)}
,
3467 SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::object, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3468 SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::embed, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3469 COMPLEX_TAG_CREATE(fieldset,{nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
3470 &nsCSSFrameConstructor::ConstructFieldSetFrame){nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
,
3471 SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame){nsGkAtoms::frameset, FrameConstructionData(NS_NewHTMLFramesetFrame
)}
,
3472 SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
3473 {nsGkAtoms::button,
3474 {ToCreationFunc(NS_NewHTMLButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewHTMLButtonControlFrame(aPs, aStyle); }
,
3475 FCDATA_ALLOW_BLOCK_STYLES0x8000 | FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000,
3476 PseudoStyleType::buttonContent}},
3477 SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData){nsGkAtoms::canvas, FrameConstructionData(nsCSSFrameConstructor
::FindCanvasData)}
,
3478 SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame){nsGkAtoms::video, FrameConstructionData(NS_NewHTMLVideoFrame
)}
,
3479 SIMPLE_TAG_CREATE(audio, NS_NewHTMLAudioFrame){nsGkAtoms::audio, FrameConstructionData(NS_NewHTMLAudioFrame
)}
,
3480 SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame){nsGkAtoms::progress, FrameConstructionData(NS_NewProgressFrame
)}
,
3481 SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame){nsGkAtoms::meter, FrameConstructionData(NS_NewMeterFrame)},
3482 SIMPLE_TAG_CHAIN(details, nsCSSFrameConstructor::FindDetailsData){nsGkAtoms::details, FrameConstructionData(nsCSSFrameConstructor
::FindDetailsData)}
,
3483 };
3484
3485 return FindDataByTag(aElement, aStyle, sHTMLData, ArrayLength(sHTMLData));
3486}
3487
3488/* static */
3489const nsCSSFrameConstructor::FrameConstructionData*
3490nsCSSFrameConstructor::FindGeneratedImageData(const Element& aElement,
3491 ComputedStyle&) {
3492 if (!aElement.IsInNativeAnonymousSubtree()) {
3493 return nullptr;
3494 }
3495
3496 auto& generatedContent = static_cast<const GeneratedImageContent&>(aElement);
3497 if (generatedContent.IsForListStyleImageMarker()) {
3498 static constexpr FrameConstructionData sImgData(
3499 NS_NewImageFrameForListStyleImage);
3500 return &sImgData;
3501 }
3502
3503 static constexpr FrameConstructionData sImgData(
3504 NS_NewImageFrameForGeneratedContentIndex);
3505 return &sImgData;
3506}
3507
3508/* static */
3509const nsCSSFrameConstructor::FrameConstructionData*
3510nsCSSFrameConstructor::FindImgData(const Element& aElement,
3511 ComputedStyle& aStyle) {
3512 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3513 nsImageFrame::ImageFrameType::ForElementRequest) {
3514 // content: url gets handled by the generic code-path.
3515 return nullptr;
3516 }
3517
3518 static constexpr FrameConstructionData sImgData(NS_NewImageFrame);
3519 return &sImgData;
3520}
3521
3522/* static */
3523const nsCSSFrameConstructor::FrameConstructionData*
3524nsCSSFrameConstructor::FindImgControlData(const Element& aElement,
3525 ComputedStyle& aStyle) {
3526 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3527 nsImageFrame::ImageFrameType::ForElementRequest) {
3528 return nullptr;
3529 }
3530
3531 static constexpr FrameConstructionData sImgControlData(
3532 NS_NewImageControlFrame);
3533 return &sImgControlData;
3534}
3535
3536/* static */
3537const nsCSSFrameConstructor::FrameConstructionData*
3538nsCSSFrameConstructor::FindSearchControlData(const Element& aElement,
3539 ComputedStyle& aStyle) {
3540 if (StaticPrefs::layout_forms_input_type_search_enabled()) {
3541 static constexpr FrameConstructionData sSearchControlData(
3542 NS_NewSearchControlFrame);
3543 return &sSearchControlData;
3544 }
3545
3546 static constexpr FrameConstructionData sTextControlData(
3547 NS_NewTextControlFrame);
3548 return &sTextControlData;
3549}
3550
3551/* static */
3552const nsCSSFrameConstructor::FrameConstructionData*
3553nsCSSFrameConstructor::FindInputData(const Element& aElement,
3554 ComputedStyle& aStyle) {
3555 static constexpr FrameConstructionDataByInt sInputData[] = {
3556 SIMPLE_INT_CREATE(FormControlType::InputCheckbox,{int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3557 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3558 SIMPLE_INT_CREATE(FormControlType::InputRadio,{int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3559 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3560 SIMPLE_INT_CREATE(FormControlType::InputFile, NS_NewFileControlFrame){int32_t(FormControlType::InputFile), FrameConstructionData(NS_NewFileControlFrame
)}
,
3561 SIMPLE_INT_CHAIN(FormControlType::InputImage,{int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
3562 nsCSSFrameConstructor::FindImgControlData){int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
,
3563 SIMPLE_INT_CREATE(FormControlType::InputEmail, NS_NewTextControlFrame){int32_t(FormControlType::InputEmail), FrameConstructionData(
NS_NewTextControlFrame)}
,
3564 SIMPLE_INT_CREATE(FormControlType::InputText, NS_NewTextControlFrame){int32_t(FormControlType::InputText), FrameConstructionData(NS_NewTextControlFrame
)}
,
3565 SIMPLE_INT_CREATE(FormControlType::InputTel, NS_NewTextControlFrame){int32_t(FormControlType::InputTel), FrameConstructionData(NS_NewTextControlFrame
)}
,
3566 SIMPLE_INT_CREATE(FormControlType::InputUrl, NS_NewTextControlFrame){int32_t(FormControlType::InputUrl), FrameConstructionData(NS_NewTextControlFrame
)}
,
3567 SIMPLE_INT_CREATE(FormControlType::InputRange, NS_NewRangeFrame){int32_t(FormControlType::InputRange), FrameConstructionData(
NS_NewRangeFrame)}
,
3568 SIMPLE_INT_CREATE(FormControlType::InputPassword, NS_NewTextControlFrame){int32_t(FormControlType::InputPassword), FrameConstructionData
(NS_NewTextControlFrame)}
,
3569 {int32_t(FormControlType::InputColor),
3570 {NS_NewColorControlFrame, 0, PseudoStyleType::buttonContent}},
3571
3572 SIMPLE_INT_CHAIN(FormControlType::InputSearch,{int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
3573 nsCSSFrameConstructor::FindSearchControlData){int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
,
3574 SIMPLE_INT_CREATE(FormControlType::InputNumber, NS_NewNumberControlFrame){int32_t(FormControlType::InputNumber), FrameConstructionData
(NS_NewNumberControlFrame)}
,
3575 SIMPLE_INT_CREATE(FormControlType::InputTime, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputTime), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3576 SIMPLE_INT_CREATE(FormControlType::InputDate, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDate), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3577 SIMPLE_INT_CREATE(FormControlType::InputDatetimeLocal,{int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
3578 NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
,
3579 // TODO: this is temporary until a frame is written: bug 888320
3580 SIMPLE_INT_CREATE(FormControlType::InputMonth, NS_NewTextControlFrame){int32_t(FormControlType::InputMonth), FrameConstructionData(
NS_NewTextControlFrame)}
,
3581 // TODO: this is temporary until a frame is written: bug 888320
3582 SIMPLE_INT_CREATE(FormControlType::InputWeek, NS_NewTextControlFrame){int32_t(FormControlType::InputWeek), FrameConstructionData(NS_NewTextControlFrame
)}
,
3583 {int32_t(FormControlType::InputSubmit),
3584 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3585 PseudoStyleType::buttonContent}},
3586 {int32_t(FormControlType::InputReset),
3587 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3588 PseudoStyleType::buttonContent}},
3589 {int32_t(FormControlType::InputButton),
3590 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3591 PseudoStyleType::buttonContent}}
3592 // Keeping hidden inputs out of here on purpose for so they get frames by
3593 // display (in practice, none).
3594 };
3595
3596 auto controlType = HTMLInputElement::FromNode(aElement)->ControlType();
3597
3598 // radio and checkbox inputs with appearance:none should be constructed
3599 // by display type. (Note that we're not checking that appearance is
3600 // not (respectively) StyleAppearance::Radio and StyleAppearance::Checkbox.)
3601 if ((controlType == FormControlType::InputCheckbox ||
3602 controlType == FormControlType::InputRadio) &&
3603 !aStyle.StyleDisplay()->HasAppearance()) {
3604 return nullptr;
3605 }
3606
3607 return FindDataByInt(int32_t(controlType), aElement, aStyle, sInputData,
3608 ArrayLength(sInputData));
3609}
3610
3611/* static */
3612const nsCSSFrameConstructor::FrameConstructionData*
3613nsCSSFrameConstructor::FindObjectData(const Element& aElement,
3614 ComputedStyle& aStyle) {
3615 uint32_t type;
3616 nsCOMPtr<nsIObjectLoadingContent> objContent =
3617 do_QueryInterface(const_cast<Element*>(&aElement));
3618 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"
, 3620); MOZ_PretendNoReturn(); } } while (0)
3619 "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"
, 3620); MOZ_PretendNoReturn(); } } while (0)
3620 "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"
, 3620); MOZ_PretendNoReturn(); } } while (0)
;
3621 objContent->GetDisplayedType(&type);
3622
3623 static constexpr FrameConstructionDataByInt sObjectData[] = {
3624 // TODO(emilio): Can we remove the NS_NewEmptyFrame case and just use a
3625 // subdocument frame here?
3626 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,{int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
3627 NS_NewEmptyFrame){int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
,
3628 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,{int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
3629 NS_NewSubDocumentFrame){int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
,
3630 // Nothing for TYPE_FALLBACK so we'll construct frames by display there
3631 };
3632
3633 return FindDataByInt((int32_t)type, aElement, aStyle, sObjectData,
3634 ArrayLength(sObjectData));
3635}
3636
3637/* static */
3638const nsCSSFrameConstructor::FrameConstructionData*
3639nsCSSFrameConstructor::FindCanvasData(const Element& aElement,
3640 ComputedStyle& aStyle) {
3641 // We want to check whether script is enabled on the document that
3642 // could be painting to the canvas. That's the owner document of
3643 // the canvas, except when the owner document is a static document,
3644 // in which case it's the original document it was cloned from.
3645 Document* doc = aElement.OwnerDoc();
3646 if (doc->IsStaticDocument()) {
3647 doc = doc->GetOriginalDocument();
3648 }
3649 if (!doc->IsScriptEnabled()) {
3650 return nullptr;
3651 }
3652
3653 static constexpr FrameConstructionData sCanvasData(
3654 NS_NewHTMLCanvasFrame, 0, PseudoStyleType::htmlCanvasContent);
3655 return &sCanvasData;
3656}
3657
3658static MOZ_NEVER_INLINE__attribute__((noinline)) void DestroyFramesInList(PresShell* aPs,
3659 nsFrameList& aList) {
3660 nsIFrame::DestroyContext context(aPs);
3661 aList.DestroyFrames(context);
3662}
3663
3664void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
3665 FrameConstructionItem& aItem, nsFrameConstructorState& aState,
3666 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
3667 const FrameConstructionData* data = aItem.mFCData;
3668 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"
, 3668); MOZ_PretendNoReturn(); } } while (0)
;
3669
3670 uint32_t bits = data->mBits;
3671
3672 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"
, 3673); MOZ_PretendNoReturn(); } } while (0)
3673 "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"
, 3673); MOZ_PretendNoReturn(); } } while (0)
;
3674
3675 // Some sets of bits are not compatible with each other
3676#define CHECK_ONLY_ONE_BIT(_bit1, _bit2) \
3677 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"
, 3678); MOZ_PretendNoReturn(); } } while (0)
3678 "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"
, 3678); MOZ_PretendNoReturn(); } } while (0)
3679 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3680 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10);
3681 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
3682 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_IS_POPUP0x100);
3683 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_SKIP_ABSPOS_PUSH0x200);
3684 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3685 FCDATA_DISALLOW_GENERATED_CONTENT0x400);
3686 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_ALLOW_BLOCK_STYLES0x8000);
3687 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3688 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3689 CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS0x20,
3690 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3691#undef CHECK_ONLY_ONE_BIT
3692 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"
, 3694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3693 !(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"
, 3694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3694 "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"
, 3694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3695 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"
, 3697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3696 (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"
, 3697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3697 "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"
, 3697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3698
3699 // Don't create a subdocument frame for iframes if we're creating extra frames
3700 if (aState.mCreatingExtraFrames &&
3701 aItem.mContent->IsHTMLElement(nsGkAtoms::iframe)) {
3702 return;
3703 }
3704
3705 nsIContent* const content = aItem.mContent;
3706 nsIFrame* newFrame;
3707 nsIFrame* primaryFrame;
3708 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3709 const nsStyleDisplay* display = computedStyle->StyleDisplay();
3710 if (bits & FCDATA_FUNC_IS_FULL_CTOR0x4) {
3711 newFrame = (this->*(data->mFunc.mFullConstructor))(
3712 aState, aItem, aParentFrame, display, aFrameList);
3713 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"
, 3713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newFrame" ") ("
"Full constructor failed" ")"); do { *((volatile int*)__null
) = 3713; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3714 primaryFrame = newFrame;
3715 } else {
3716 newFrame = (*data->mFunc.mCreationFunc)(mPresShell, computedStyle);
3717
3718 const bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8);
3719 const bool isPopup = aItem.mIsPopup;
3720
3721 nsContainerFrame* geometricParent =
3722 (isPopup || allowOutOfFlow)
3723 ? aState.GetGeometricParent(*display, aParentFrame)
3724 : aParentFrame;
3725
3726 // In the non-scrollframe case, primaryFrame and newFrame are equal; in the
3727 // scrollframe case, newFrame is the scrolled frame while primaryFrame is
3728 // the scrollframe.
3729 if ((bits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3730 display->IsScrollableOverflow()) {
3731 nsContainerFrame* scrollframe = nullptr;
3732 BuildScrollContainerFrame(aState, content, computedStyle, newFrame,
3733 geometricParent, scrollframe);
3734 primaryFrame = scrollframe;
3735 } else {
3736 InitAndRestoreFrame(aState, content, geometricParent, newFrame);
3737 primaryFrame = newFrame;
3738 }
3739
3740 // If we need to create a block formatting context to wrap our
3741 // kids, do it now.
3742 nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
3743 nsIFrame* maybeAbsoluteContainingBlock = newFrame;
3744 nsIFrame* possiblyLeafFrame = newFrame;
3745 nsContainerFrame* outerFrame = nullptr;
3746 if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000) {
3747 RefPtr<ComputedStyle> outerStyle =
3748 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3749 data->mAnonBoxPseudo, computedStyle);
3750#ifdef DEBUG1
3751 nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
3752 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"
, 3752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containerFrame"
")"); do { *((volatile int*)__null) = 3752; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3753#endif
3754 nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
3755 nsContainerFrame* innerFrame;
3756 if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) {
3757 switch (display->DisplayInside()) {
3758 case StyleDisplayInside::Flex:
3759 outerFrame = NS_NewFlexContainerFrame(mPresShell, outerStyle);
3760 InitAndRestoreFrame(aState, content, container, outerFrame);
3761 innerFrame = outerFrame;
3762 break;
3763 case StyleDisplayInside::Grid:
3764 outerFrame = NS_NewGridContainerFrame(mPresShell, outerStyle);
3765 InitAndRestoreFrame(aState, content, container, outerFrame);
3766 innerFrame = outerFrame;
3767 break;
3768 default: {
3769 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3770 if (outerStyle->StyleColumn()->IsColumnContainerStyle()) {
3771 outerFrame = BeginBuildingColumns(aState, content, container,
3772 innerFrame, outerStyle);
3773 } else {
3774 // No need to create column container. Initialize innerFrame.
3775 InitAndRestoreFrame(aState, content, container, innerFrame);
3776 outerFrame = innerFrame;
3777 }
3778 break;
3779 }
3780 }
3781 } else {
3782 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3783 InitAndRestoreFrame(aState, content, container, innerFrame);
3784 outerFrame = innerFrame;
3785 }
3786
3787 SetInitialSingleChild(container, outerFrame);
3788
3789 container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3790
3791 // Now figure out whether newFrame or outerFrame should be the
3792 // absolute container.
3793 if (outerFrame->IsAbsPosContainingBlock()) {
3794 maybeAbsoluteContainingBlock = outerFrame;
3795 maybeAbsoluteContainingBlockStyleFrame = outerFrame;
3796 innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3797 }
3798
3799 // Our kids should go into the innerFrame.
3800 newFrame = innerFrame;
3801 }
3802
3803 aState.AddChild(primaryFrame, aFrameList, content, aParentFrame,
3804 allowOutOfFlow, allowOutOfFlow);
3805
3806 nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
3807 if (newFrameAsContainer) {
3808 // Process the child content if requested
3809 nsFrameList childList;
3810 nsFrameConstructorSaveState absoluteSaveState;
3811
3812 if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10) {
3813 aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
3814 } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH0x200)) {
3815 maybeAbsoluteContainingBlock->AddStateBits(
3816 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3817 if (maybeAbsoluteContainingBlockStyleFrame->IsAbsPosContainingBlock()) {
3818 auto* cf =
3819 static_cast<nsContainerFrame*>(maybeAbsoluteContainingBlock);
3820 aState.PushAbsoluteContainingBlock(
3821 cf, maybeAbsoluteContainingBlockStyleFrame, absoluteSaveState);
3822 }
3823 }
3824
3825 nsFrameConstructorSaveState floatSaveState;
3826 aState.MaybePushFloatContainingBlock(newFrameAsContainer, floatSaveState);
3827
3828 if (bits & FCDATA_USE_CHILD_ITEMS0x10000) {
3829 // At this point, we have not set up the auto value for this frame, and
3830 // no caller will have set it so it is not redundant and therefor will
3831 // not assert.
3832 AutoFrameConstructionPageName pageNameTracker(aState,
3833 newFrameAsContainer);
3834 ConstructFramesFromItemList(
3835 aState, aItem.mChildItems, newFrameAsContainer,
3836 bits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
3837 } else {
3838 // Process the child frames.
3839 ProcessChildren(aState, content, computedStyle, newFrameAsContainer,
3840 !(bits & FCDATA_DISALLOW_GENERATED_CONTENT0x400), childList,
3841 (bits & FCDATA_ALLOW_BLOCK_STYLES0x8000) != 0,
3842 possiblyLeafFrame);
3843 }
3844
3845 if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS0x20) {
3846 nsFrameList newList;
3847 nsFrameList currentBlockList;
3848 nsIFrame* f;
3849 while ((f = childList.FirstChild()) != nullptr) {
3850 bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
3851 if (!wrapFrame) {
3852 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3853 currentBlockList, newList);
3854 }
3855
3856 childList.RemoveFrame(f);
3857 if (wrapFrame) {
3858 currentBlockList.AppendFrame(nullptr, f);
3859 } else {
3860 newList.AppendFrame(nullptr, f);
3861 }
3862 }
3863 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3864 currentBlockList, newList);
3865
3866 if (childList.NotEmpty()) {
3867 // an error must have occurred, delete unprocessed frames
3868 DestroyFramesInList(mPresShell, childList);
3869 }
3870
3871 childList = std::move(newList);
3872 }
3873
3874 if (!(bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) ||
3875 !MayNeedToCreateColumnSpanSiblings(newFrameAsContainer, childList)) {
3876 // Set the frame's initial child list. Note that MathML depends on this
3877 // being called even if childList is empty!
3878 newFrameAsContainer->SetInitialChildList(FrameChildListID::Principal,
3879 std::move(childList));
3880 } else {
3881 // Extract any initial non-column-span kids, and put them in inner
3882 // frame's child list.
3883 nsFrameList initialNonColumnSpanKids =
3884 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3885 newFrameAsContainer->SetInitialChildList(
3886 FrameChildListID::Principal, std::move(initialNonColumnSpanKids));
3887
3888 if (childList.NotEmpty()) {
3889 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3890 aState, newFrameAsContainer, childList,
3891 // Column content should never be a absolute/fixed positioned
3892 // containing block. Pass nullptr as aPositionedFrame.
3893 nullptr);
3894
3895 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"
, 3897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3897; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3896 "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"
, 3897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3897; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3897 "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"
, 3897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3897; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
3898 FinishBuildingColumns(aState, outerFrame, newFrameAsContainer,
3899 columnSpanSiblings);
3900 }
3901 }
3902 }
3903 }
3904
3905 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"
, 3907); MOZ_PretendNoReturn(); } } while (0)
3906 ((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"
, 3907); MOZ_PretendNoReturn(); } } while (0)
3907 "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"
, 3907); MOZ_PretendNoReturn(); } } while (0)
;
3908
3909 // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
3910 // generated content that doesn't have one yet. Note that we have to examine
3911 // the frame bit, because by this point mIsGeneratedContent has been cleared
3912 // on aItem.
3913 if ((!aState.mCreatingExtraFrames ||
3914 (aItem.mContent->IsRootOfNativeAnonymousSubtree() &&
3915 !aItem.mContent->GetPrimaryFrame())) &&
3916 !(bits & FCDATA_SKIP_FRAMESET0x1)) {
3917 aItem.mContent->SetPrimaryFrame(primaryFrame);
3918 ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
3919 }
3920}
3921
3922static void GatherSubtreeElements(Element* aElement,
3923 nsTArray<Element*>& aElements) {
3924 aElements.AppendElement(aElement);
3925 StyleChildrenIterator iter(aElement);
3926 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
3927 if (!c->IsElement()) {
3928 continue;
3929 }
3930 GatherSubtreeElements(c->AsElement(), aElements);
3931 }
3932}
3933
3934nsresult nsCSSFrameConstructor::GetAnonymousContent(
3935 nsIContent* aParent, nsIFrame* aParentFrame,
3936 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent) {
3937 nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
3938 if (!creator) {
3939 return NS_OK;
3940 }
3941
3942 nsresult rv = creator->CreateAnonymousContent(aContent);
3943 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3944 // CreateAnonymousContent failed, e.g. because the page has a <use> loop.
3945 return rv;
3946 }
3947
3948 if (aContent.IsEmpty()) {
3949 return NS_OK;
3950 }
3951
3952 const bool devtoolsEventsEnabled =
3953 mDocument->DevToolsAnonymousAndShadowEventsEnabled();
3954
3955 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"
, 3955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsElement()"
")"); do { *((volatile int*)__null) = 3955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3956 for (const auto& info : aContent) {
3957 // get our child's content and set its parent to our content
3958 nsIContent* content = info.mContent;
3959 content->SetIsNativeAnonymousRoot();
3960
3961 BindContext context(*aParent->AsElement(), BindContext::ForNativeAnonymous);
3962 rv = content->BindToTree(context, *aParent);
3963
3964 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3965 content->UnbindFromTree();
3966 return rv;
3967 }
3968
3969 if (devtoolsEventsEnabled) {
3970 content->QueueDevtoolsAnonymousEvent(/* aIsRemove = */ false);
3971 }
3972 }
3973
3974 // Some situations where we don't cache anonymous content styles:
3975 //
3976 // * when visibility or pointer-events is anything other than the initial
3977 // value; we rely on visibility and pointer-events inheriting into anonymous
3978 // content, but don't bother adding this state to the AnonymousContentKey,
3979 // since it's not so common. Note that with overlay scrollbars, scrollbars
3980 // always start off with pointer-events: none so we don't need to check for
3981 // that in that case.
3982 //
3983 // * when the medium is anything other than screen; some UA style sheet rules
3984 // apply in e.g. print medium, and will give different results from the
3985 // cached styles
3986 Maybe<bool> computedAllowStyleCaching;
3987 auto ComputeAllowStyleCaching = [&] {
3988 if (!StaticPrefs::layout_css_cached_scrollbar_styles_enabled()) {
3989 return false;
3990 }
3991 if (aParentFrame->StyleVisibility()->mVisible != StyleVisibility::Visible) {
3992 return false;
3993 }
3994 nsPresContext* pc = mPresShell->GetPresContext();
3995 if (!pc->UseOverlayScrollbars() &&
3996 aParentFrame->StyleUI()->ComputedPointerEvents() !=
3997 StylePointerEvents::Auto) {
3998 return false;
3999 }
4000 if (pc->Medium() != nsGkAtoms::screen) {
4001 return false;
4002 }
4003 return true;
4004 };
4005
4006 auto AllowStyleCaching = [&] {
4007 if (computedAllowStyleCaching.isNothing()) {
4008 computedAllowStyleCaching.emplace(ComputeAllowStyleCaching());
4009 }
4010 return computedAllowStyleCaching.value();
4011 };
4012
4013 // Compute styles for the anonymous content tree.
4014 ServoStyleSet* styleSet = mPresShell->StyleSet();
4015 for (auto& info : aContent) {
4016 Element* e = Element::FromNode(info.mContent);
4017 if (!e) {
4018 continue;
4019 }
4020
4021 if (info.mKey == AnonymousContentKey::None || !AllowStyleCaching()) {
4022 // Most NAC subtrees do not use caching of computed styles. Just go
4023 // ahead and eagerly style the subtree.
4024 styleSet->StyleNewSubtree(e);
4025 continue;
4026 }
4027
4028 // We have a NAC subtree for which we can use cached styles.
4029 AutoTArray<RefPtr<ComputedStyle>, 2> cachedStyles;
4030 AutoTArray<Element*, 2> elements;
4031
4032 GatherSubtreeElements(e, elements);
4033 styleSet->GetCachedAnonymousContentStyles(info.mKey, cachedStyles);
4034
4035 if (cachedStyles.IsEmpty()) {
4036 // We haven't stored cached styles for this kind of NAC subtree yet.
4037 // Eagerly compute those styles, then cache them for later.
4038 styleSet->StyleNewSubtree(e);
4039 for (Element* e : elements) {
4040 if (e->HasServoData()) {
4041 cachedStyles.AppendElement(ServoStyleSet::ResolveServoStyle(*e));
4042 } else {
4043 cachedStyles.AppendElement(nullptr);
4044 }
4045 }
4046 styleSet->PutCachedAnonymousContentStyles(info.mKey,
4047 std::move(cachedStyles));
4048 continue;
4049 }
4050
4051 // We previously stored cached styles for this kind of NAC subtree.
4052 // Iterate over them and set them on the subtree's elements.
4053 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"
, 4054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4054; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4054 "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"
, 4054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4054; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4055 for (size_t i = 0, len = cachedStyles.Length(); i != len; ++i) {
4056 if (cachedStyles[i]) {
4057#ifdef DEBUG1
4058 // Assert that our cached style is the same as one we could compute.
4059 RefPtr<ComputedStyle> cs = styleSet->ResolveStyleLazily(*elements[i]);
4060 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"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4063; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4061 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"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4063; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4062 "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"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4063; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4063 "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"
, 4063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4063; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4064 // All overlay scrollbars start off as inactive, so we can rely on their
4065 // pointer-events value being always none.
4066 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4067 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4068 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4068; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4069#endif
4070 Servo_SetExplicitStyle(elements[i], cachedStyles[i]);
4071 }
4072 }
4073 }
4074
4075 return NS_OK;
4076}
4077
4078// XUL frames are not allowed to be out of flow.
4079#define SIMPLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200) \
4080 FrameConstructionData(_func, \
4081 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_SKIP_ABSPOS_PUSH0x200)
4082#define SCROLLABLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200 | 0x80) \
4083 FrameConstructionData(_func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4084 FCDATA_SKIP_ABSPOS_PUSH0x200 | \
4085 FCDATA_MAY_NEED_SCROLLFRAME0x80)
4086// .. but we allow some XUL frames to be _containers_ for out-of-flow content
4087// (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
4088#define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)FrameConstructionData( _func, 0x8 | 0x80) \
4089 FrameConstructionData( \
4090 _func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_MAY_NEED_SCROLLFRAME0x80)
4091
4092#define SIMPLE_XUL_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func, 0x8 | 0x200)} \
4093 {nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200)}
4094#define SCROLLABLE_XUL_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func, 0x8 | 0x200 | 0x80
)}
\
4095 {nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func)FrameConstructionData(_func, 0x8 | 0x200 | 0x80)}
4096
4097/* static */
4098const nsCSSFrameConstructor::FrameConstructionData*
4099nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
4100 ComputedStyle& aStyle) {
4101 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"
, 4101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsXULElement()"
")"); do { *((volatile int*)__null) = 4101; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4102 static constexpr FrameConstructionData kPopupData(
4103 NS_NewMenuPopupFrame, FCDATA_IS_POPUP0x100 | FCDATA_SKIP_ABSPOS_PUSH0x200);
4104
4105 static constexpr FrameConstructionDataByTag sXULTagData[] = {
4106 SIMPLE_XUL_CREATE(image, NS_NewXULImageFrame){nsGkAtoms::image, FrameConstructionData(NS_NewXULImageFrame,
0x8 | 0x200)}
,
4107 SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame){nsGkAtoms::treechildren, FrameConstructionData(NS_NewTreeBodyFrame
, 0x8 | 0x200)}
,
4108 SIMPLE_TAG_CHAIN(label,{nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4109 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4110 SIMPLE_TAG_CHAIN(description,{nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4111 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4112#ifdef XP_MACOSX
4113 SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData){nsGkAtoms::menubar, FrameConstructionData(nsCSSFrameConstructor
::FindXULMenubarData)}
,
4114#endif /* XP_MACOSX */
4115 SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4116 SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame){nsGkAtoms::editor, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4117 SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame){nsGkAtoms::browser, FrameConstructionData(NS_NewSubDocumentFrame
, 0x8 | 0x200)}
,
4118 SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame){nsGkAtoms::splitter, FrameConstructionData(NS_NewSplitterFrame
, 0x8 | 0x200)}
,
4119 SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame){nsGkAtoms::scrollbar, FrameConstructionData(NS_NewScrollbarFrame
, 0x8 | 0x200)}
,
4120 SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame){nsGkAtoms::slider, FrameConstructionData(NS_NewSliderFrame, 0x8
| 0x200)}
,
4121 SIMPLE_XUL_CREATE(thumb, NS_NewSimpleXULLeafFrame){nsGkAtoms::thumb, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4122 SIMPLE_XUL_CREATE(scrollcorner, NS_NewSimpleXULLeafFrame){nsGkAtoms::scrollcorner, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4123 SIMPLE_XUL_CREATE(resizer, NS_NewSimpleXULLeafFrame){nsGkAtoms::resizer, FrameConstructionData(NS_NewSimpleXULLeafFrame
, 0x8 | 0x200)}
,
4124 SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame){nsGkAtoms::scrollbarbutton, FrameConstructionData(NS_NewScrollbarButtonFrame
, 0x8 | 0x200)}
,
4125 {nsGkAtoms::panel, kPopupData},
4126 {nsGkAtoms::menupopup, kPopupData},
4127 {nsGkAtoms::tooltip, kPopupData},
4128 };
4129
4130 return FindDataByTag(aElement, aStyle, sXULTagData, ArrayLength(sXULTagData));
4131}
4132
4133/* static */
4134const nsCSSFrameConstructor::FrameConstructionData*
4135nsCSSFrameConstructor::FindXULLabelOrDescriptionData(const Element& aElement,
4136 ComputedStyle&) {
4137 // Follow CSS display value if no value attribute
4138 if (!aElement.HasAttr(nsGkAtoms::value)) {
4139 return nullptr;
4140 }
4141
4142 // Follow CSS display if there's no crop="center".
4143 if (!aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::crop,
4144 nsGkAtoms::center, eCaseMatters)) {
4145 return nullptr;
4146 }
4147
4148 static constexpr FrameConstructionData sMiddleCroppingData =
4149 SIMPLE_XUL_FCDATA(NS_NewMiddleCroppingLabelFrame)FrameConstructionData(NS_NewMiddleCroppingLabelFrame, 0x8 | 0x200
)
;
4150 return &sMiddleCroppingData;
4151}
4152
4153#ifdef XP_MACOSX
4154/* static */
4155const nsCSSFrameConstructor::FrameConstructionData*
4156nsCSSFrameConstructor::FindXULMenubarData(const Element& aElement,
4157 ComputedStyle&) {
4158 if (aElement.OwnerDoc()->IsInChromeDocShell()) {
4159 BrowsingContext* bc = aElement.OwnerDoc()->GetBrowsingContext();
4160 bool isRoot = bc && !bc->GetParent();
4161 if (isRoot) {
4162 // This is the root. Suppress the menubar, since on Mac
4163 // window menus are not attached to the window.
4164 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4165 return &sSuppressData;
4166 }
4167 }
4168
4169 return nullptr;
4170}
4171#endif /* XP_MACOSX */
4172
4173already_AddRefed<ComputedStyle>
4174nsCSSFrameConstructor::BeginBuildingScrollContainerFrame(
4175 nsFrameConstructorState& aState, nsIContent* aContent,
4176 ComputedStyle* aContentStyle, nsContainerFrame* aParentFrame,
4177 PseudoStyleType aScrolledPseudo, bool aIsRoot,
4178 nsContainerFrame*& aNewFrame) {
4179 nsContainerFrame* scrollContainerFrame = aNewFrame;
4180
4181 if (!scrollContainerFrame) {
4182 scrollContainerFrame =
4183 NS_NewScrollContainerFrame(mPresShell, aContentStyle, aIsRoot);
4184 InitAndRestoreFrame(aState, aContent, aParentFrame, scrollContainerFrame);
4185 }
4186
4187 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"
, 4187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scrollContainerFrame"
")"); do { *((volatile int*)__null) = 4187; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4188
4189 // if there are any anonymous children for the scroll frame, create
4190 // frames for them.
4191 //
4192 // We can't take the normal ProcessChildren path, because the NAC needs to
4193 // be parented to the scrollframe, and everything else needs to be parented
4194 // to the scrolledframe.
4195 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC;
4196 DebugOnly<nsresult> rv =
4197 GetAnonymousContent(aContent, scrollContainerFrame, scrollNAC);
4198 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"
, 4198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4198; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4199 nsFrameList anonymousList;
4200 if (!scrollNAC.IsEmpty()) {
4201 nsFrameConstructorSaveState floatSaveState;
4202 aState.MaybePushFloatContainingBlock(scrollContainerFrame, floatSaveState);
4203
4204 AutoFrameConstructionItemList items(this);
4205 AutoFrameConstructionPageName pageNameTracker(aState, scrollContainerFrame);
4206 AddFCItemsForAnonymousContent(aState, scrollContainerFrame, scrollNAC,
4207 items, pageNameTracker);
4208 ConstructFramesFromItemList(aState, items, scrollContainerFrame,
4209 /* aParentIsWrapperAnonBox = */ false,
4210 anonymousList);
4211 }
4212
4213 aNewFrame = scrollContainerFrame;
4214 scrollContainerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4215
4216 // we used the style that was passed in. So resolve another one.
4217 ServoStyleSet* styleSet = mPresShell->StyleSet();
4218 RefPtr<ComputedStyle> scrolledChildStyle =
4219 styleSet->ResolveInheritingAnonymousBoxStyle(aScrolledPseudo,
4220 aContentStyle);
4221
4222 scrollContainerFrame->SetInitialChildList(FrameChildListID::Principal,
4223 std::move(anonymousList));
4224
4225 return scrolledChildStyle.forget();
4226}
4227
4228void nsCSSFrameConstructor::FinishBuildingScrollContainerFrame(
4229 nsContainerFrame* aScrollContainerFrame, nsIFrame* aScrolledFrame) {
4230 aScrollContainerFrame->AppendFrames(
4231 FrameChildListID::Principal, nsFrameList(aScrolledFrame, aScrolledFrame));
4232}
4233
4234void nsCSSFrameConstructor::BuildScrollContainerFrame(
4235 nsFrameConstructorState& aState, nsIContent* aContent,
4236 ComputedStyle* aContentStyle, nsIFrame* aScrolledFrame,
4237 nsContainerFrame* aParentFrame, nsContainerFrame*& aNewFrame) {
4238 RefPtr<ComputedStyle> scrolledContentStyle =
4239 BeginBuildingScrollContainerFrame(
4240 aState, aContent, aContentStyle, aParentFrame,
4241 PseudoStyleType::scrolledContent, false, aNewFrame);
4242
4243 aScrolledFrame->SetComputedStyleWithoutNotification(scrolledContentStyle);
4244 InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
4245
4246 FinishBuildingScrollContainerFrame(aNewFrame, aScrolledFrame);
4247}
4248
4249const nsCSSFrameConstructor::FrameConstructionData*
4250nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
4251 const Element& aElement) {
4252 static_assert(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET28)),
4253 "Check eParentTypeCount should not overflow");
4254
4255 // The style system ensures that floated and positioned frames are
4256 // block-level.
4257 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"
, 4260); MOZ_PretendNoReturn(); } } while (0)
4258 !(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"
, 4260); MOZ_PretendNoReturn(); } } while (0)
4259 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"
, 4260); MOZ_PretendNoReturn(); } } while (0)
4260 "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"
, 4260); MOZ_PretendNoReturn(); } } while (0)
;
4261
4262 // If this is "body", try propagating its scroll style to the viewport
4263 // Note that we need to do this even if the body is NOT scrollable;
4264 // it might have dynamically changed from scrollable to not scrollable,
4265 // and that might need to be propagated.
4266 // XXXbz is this the right place to do this? If this code moves,
4267 // make this function static.
4268 bool propagatedScrollToViewport = false;
4269 if (aElement.IsHTMLElement(nsGkAtoms::body)) {
4270 if (nsPresContext* presContext = mPresShell->GetPresContext()) {
4271 propagatedScrollToViewport =
4272 presContext->UpdateViewportScrollStylesOverride() == &aElement;
4273 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"
, 4275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4274 !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"
, 4275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4275 "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"
, 4275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4276 }
4277 }
4278
4279 switch (aDisplay.DisplayInside()) {
4280 case StyleDisplayInside::Flow:
4281 case StyleDisplayInside::FlowRoot: {
4282 if (aDisplay.IsInlineFlow()) {
4283 static constexpr FrameConstructionData data(
4284 &nsCSSFrameConstructor::ConstructInline,
4285 FCDATA_IS_INLINE0x1000 | FCDATA_IS_LINE_PARTICIPANT0x2000);
4286 return &data;
4287 }
4288
4289 // If the frame is a block-level frame and is scrollable, then wrap it in
4290 // a scroll frame. Except we don't want to do that for paginated contexts
4291 // for frames that are block-outside and aren't frames for native
4292 // anonymous stuff.
4293 // XXX Ignore tables for the time being (except caption)
4294 const uint32_t kCaptionCtorFlags =
4295 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28);
4296 const bool caption = aDisplay.mDisplay == StyleDisplay::TableCaption;
4297 const bool needScrollFrame =
4298 aDisplay.IsScrollableOverflow() && !propagatedScrollToViewport;
4299 if (needScrollFrame) {
4300 const bool suppressScrollFrame =
4301 mPresShell->GetPresContext()->IsPaginated() &&
4302 aDisplay.IsBlockOutsideStyle() &&
4303 !aElement.IsInNativeAnonymousSubtree();
4304 if (!suppressScrollFrame) {
4305 static constexpr FrameConstructionData sScrollableBlockData[2] = {
4306 {&nsCSSFrameConstructor::ConstructScrollableBlock},
4307 {&nsCSSFrameConstructor::ConstructScrollableBlock,
4308 kCaptionCtorFlags}};
4309 return &sScrollableBlockData[caption];
4310 }
4311 }
4312
4313 // Handle various non-scrollable blocks.
4314 static constexpr FrameConstructionData sNonScrollableBlockData[2] = {
4315 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
4316 {&nsCSSFrameConstructor::ConstructNonScrollableBlock,
4317 kCaptionCtorFlags}};
4318 return &sNonScrollableBlockData[caption];
4319 }
4320 case StyleDisplayInside::Table: {
4321 static constexpr FrameConstructionData data(
4322 &nsCSSFrameConstructor::ConstructTable);
4323 return &data;
4324 }
4325 // NOTE: In the unlikely event that we add another table-part here that
4326 // has a desired-parent-type (& hence triggers table fixup), we'll need to
4327 // also update the flexbox chunk in ComputedStyle::ApplyStyleFixups().
4328 case StyleDisplayInside::TableRowGroup: {
4329 static constexpr FrameConstructionData data(
4330 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4331 FCDATA_IS_TABLE_PART0x800 |
4332 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4333 return &data;
4334 }
4335 case StyleDisplayInside::TableColumn: {
4336 static constexpr FrameConstructionData data(
4337 &nsCSSFrameConstructor::ConstructTableCol,
4338 FCDATA_IS_TABLE_PART0x800 |
4339 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup)(((uint32_t)(eTypeColGroup)) << 28));
4340 return &data;
4341 }
4342 case StyleDisplayInside::TableColumnGroup: {
4343 static constexpr FrameConstructionData data(
4344 ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
4345 FCDATA_IS_TABLE_PART0x800 | FCDATA_DISALLOW_OUT_OF_FLOW0x8 |
4346 FCDATA_SKIP_ABSPOS_PUSH0x200 |
4347 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4348 return &data;
4349 }
4350 case StyleDisplayInside::TableHeaderGroup: {
4351 static constexpr FrameConstructionData data(
4352 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4353 FCDATA_IS_TABLE_PART0x800 |
4354 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4355 return &data;
4356 }
4357 case StyleDisplayInside::TableFooterGroup: {
4358 static constexpr FrameConstructionData data(
4359 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4360 FCDATA_IS_TABLE_PART0x800 |
4361 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4362 return &data;
4363 }
4364 case StyleDisplayInside::TableRow: {
4365 static constexpr FrameConstructionData data(
4366 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4367 FCDATA_IS_TABLE_PART0x800 |
4368 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28));
4369 return &data;
4370 }
4371 case StyleDisplayInside::TableCell: {
4372 static constexpr FrameConstructionData data(
4373 &nsCSSFrameConstructor::ConstructTableCell,
4374 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28));
4375 return &data;
4376 }
4377 case StyleDisplayInside::Flex:
4378 case StyleDisplayInside::WebkitBox: {
4379 static constexpr FrameConstructionData nonScrollableData(
4380 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
);
4381 static constexpr FrameConstructionData data(
4382 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
,
4383 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4384 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4385 : &data;
4386 }
4387 case StyleDisplayInside::Grid: {
4388 static constexpr FrameConstructionData nonScrollableData(
4389 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
);
4390 static constexpr FrameConstructionData data(
4391 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
,
4392 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4393 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4394 : &data;
4395 }
4396 case StyleDisplayInside::Ruby: {
4397 static constexpr FrameConstructionData data[] = {
4398 {&nsCSSFrameConstructor::ConstructBlockRubyFrame,
4399 FCDATA_MAY_NEED_SCROLLFRAME0x80},
4400 {ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
, FCDATA_IS_LINE_PARTICIPANT0x2000}};
4401 bool isInline = aDisplay.DisplayOutside() == StyleDisplayOutside::Inline;
4402 return &data[isInline];
4403 }
4404 case StyleDisplayInside::RubyBase: {
4405 static constexpr FrameConstructionData data(
4406 ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
4407 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4408 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28));
4409 return &data;
4410 }
4411 case StyleDisplayInside::RubyBaseContainer: {
4412 static constexpr FrameConstructionData data(
4413 ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
4414 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4415 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4416 return &data;
4417 }
4418 case StyleDisplayInside::RubyText: {
4419 static constexpr FrameConstructionData data(
4420 ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
4421 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4422 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28));
4423 return &data;
4424 }
4425 case StyleDisplayInside::RubyTextContainer: {
4426 static constexpr FrameConstructionData data(
4427 ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
4428 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4429 return &data;
4430 }
4431 default:
4432 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"
, 4432); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unknown 'display' value" ")"); do
{ *((volatile int*)__null) = 4432; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4433 return nullptr;
4434 }
4435}
4436
4437nsIFrame* nsCSSFrameConstructor::ConstructScrollableBlock(
4438 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4439 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4440 nsFrameList& aFrameList) {
4441 nsIContent* const content = aItem.mContent;
4442 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4443
4444 nsContainerFrame* newFrame = nullptr;
4445 RefPtr<ComputedStyle> scrolledContentStyle =
4446 BeginBuildingScrollContainerFrame(
4447 aState, content, computedStyle,
4448 aState.GetGeometricParent(*aDisplay, aParentFrame),
4449 PseudoStyleType::scrolledContent, false, newFrame);
4450
4451 // Create our block frame
4452 // pass a temporary stylecontext, the correct one will be set later
4453 nsContainerFrame* scrolledFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4454
4455 // Make sure to AddChild before we call ConstructBlock so that we
4456 // end up before our descendants in fixed-pos lists as needed.
4457 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
4458
4459 nsFrameList blockList;
4460 ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
4461 &scrolledFrame, blockList,
4462 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4463
4464 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"
, 4465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4465 "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"
, 4465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4466 FinishBuildingScrollContainerFrame(newFrame, scrolledFrame);
4467
4468 return newFrame;
4469}
4470
4471nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlock(
4472 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4473 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4474 nsFrameList& aFrameList) {
4475 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4476 nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4477 ConstructBlock(aState, aItem.mContent,
4478 aState.GetGeometricParent(*aDisplay, aParentFrame),
4479 aParentFrame, computedStyle, &newFrame, aFrameList,
4480 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4481 return newFrame;
4482}
4483
4484void nsCSSFrameConstructor::InitAndRestoreFrame(
4485 const nsFrameConstructorState& aState, nsIContent* aContent,
4486 nsContainerFrame* aParentFrame, nsIFrame* aNewFrame, bool aAllowCounters) {
4487 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"
, 4487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame" ") ("
"Null frame cannot be initialized" ")"); do { *((volatile int
*)__null) = 4487; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4488
4489 // Initialize the frame
4490 aNewFrame->Init(aContent, aParentFrame, nullptr);
4491 aNewFrame->AddStateBits(aState.mAdditionalStateBits);
4492
4493 if (aState.mFrameState) {
4494 // Restore frame state for just the newly created frame.
4495 RestoreFrameStateFor(aNewFrame, aState.mFrameState);
4496 }
4497
4498 if (aAllowCounters &&
4499 mContainStyleScopeManager.AddCounterChanges(aNewFrame)) {
4500 CountersDirty();
4501 }
4502}
4503
4504already_AddRefed<ComputedStyle> nsCSSFrameConstructor::ResolveComputedStyle(
4505 nsIContent* aContent) {
4506 if (auto* element = Element::FromNode(aContent)) {
4507 return ServoStyleSet::ResolveServoStyle(*element);
4508 }
4509
4510 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"
, 4512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4511 "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"
, 4512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4512 "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"
, 4512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4513
4514 Element* parent = aContent->GetFlattenedTreeParentElement();
4515 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"
, 4515); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"Text out of the flattened tree?" ")"); do { *((volatile int
*)__null) = 4515; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4516
4517 // FIXME(emilio): The const_cast is unfortunate, but it's not worse than what
4518 // we did before.
4519 //
4520 // We could use ResolveServoStyle, but that would involve extra unnecessary
4521 // refcount traffic...
4522 auto* parentStyle =
4523 const_cast<ComputedStyle*>(Servo_Element_GetMaybeOutOfDateStyle(parent));
4524 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"
, 4525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4525; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4525 "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"
, 4525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4525; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4526 return mPresShell->StyleSet()->ResolveStyleForText(aContent, parentStyle);
4527}
4528
4529// MathML Mod - RBS
4530void nsCSSFrameConstructor::FlushAccumulatedBlock(
4531 nsFrameConstructorState& aState, nsIContent* aContent,
4532 nsContainerFrame* aParentFrame, nsFrameList& aBlockList,
4533 nsFrameList& aNewList) {
4534 if (aBlockList.IsEmpty()) {
4535 // Nothing to do
4536 return;
4537 }
4538
4539 auto anonPseudo = PseudoStyleType::mozMathMLAnonymousBlock;
4540
4541 ComputedStyle* parentContext =
4542 nsIFrame::CorrectStyleParentFrame(aParentFrame, anonPseudo)->Style();
4543 ServoStyleSet* styleSet = mPresShell->StyleSet();
4544 RefPtr<ComputedStyle> blockContext =
4545 styleSet->ResolveInheritingAnonymousBoxStyle(anonPseudo, parentContext);
4546
4547 // then, create a block frame that will wrap the child frames. Make it a
4548 // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
4549 // is not a suitable block.
4550 nsContainerFrame* blockFrame =
4551 NS_NewMathMLmathBlockFrame(mPresShell, blockContext);
4552
4553 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
4554 ReparentFrames(this, blockFrame, aBlockList, false);
4555 // We have to walk over aBlockList before we hand it over to blockFrame.
4556 for (nsIFrame* f : aBlockList) {
4557 f->SetParentIsWrapperAnonBox();
4558 }
4559 // abs-pos and floats are disabled in MathML children so we don't have to
4560 // worry about messing up those.
4561 blockFrame->SetInitialChildList(FrameChildListID::Principal,
4562 std::move(aBlockList));
4563 aNewList.AppendFrame(nullptr, blockFrame);
4564}
4565
4566// Only <math> elements can be floated or positioned. All other MathML
4567// should be in-flow.
4568#define SIMPLE_MATHML_CREATE(_tag, _func){ nsGkAtoms::_tag, { _func, 0x8 | 0x10 | 0x20 } } \
4569 { \
4570 nsGkAtoms::_tag, { \
4571 _func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4572 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | \
4573 FCDATA_WRAP_KIDS_IN_BLOCKS0x20 \
4574 } \
4575 }
4576
4577/* static */
4578const nsCSSFrameConstructor::FrameConstructionData*
4579nsCSSFrameConstructor::FindMathMLData(const Element& aElement,
4580 ComputedStyle& aStyle) {
4581 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"
, 4581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsMathMLElement()"
")"); do { *((volatile int*)__null) = 4581; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4582
4583 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4584
4585 // Handle <math> specially, because it sometimes produces inlines
4586 if (tag == nsGkAtoms::math) {
4587 // The IsBlockOutsideStyle() check must match what
4588 // specified::Display::equivalent_block_display is checking for
4589 // already-block-outside things. Though the behavior here for the
4590 // display:table case is pretty weird...
4591 if (aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
4592 static constexpr FrameConstructionData sBlockMathData(
4593 ToCreationFunc(NS_NewMathMLmathBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathBlockFrame(aPs, aStyle); }
,
4594 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4595 return &sBlockMathData;
4596 }
4597
4598 static constexpr FrameConstructionData sInlineMathData(
4599 ToCreationFunc(NS_NewMathMLmathInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathInlineFrame(aPs, aStyle); }
,
4600 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4601 FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4602 return &sInlineMathData;
4603 }
4604
4605 static constexpr FrameConstructionDataByTag sMathMLData[] = {
4606 SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame){ nsGkAtoms::annotation_, { NS_NewMathMLTokenFrame, 0x8 | 0x10
| 0x20 } }
,
4607 SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame){ nsGkAtoms::annotation_xml_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4608 SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame){ nsGkAtoms::mi_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4609 SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame){ nsGkAtoms::mn_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4610 SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame){ nsGkAtoms::ms_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4611 SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame){ nsGkAtoms::mtext_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4612 SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame){ nsGkAtoms::mo_, { NS_NewMathMLmoFrame, 0x8 | 0x10 | 0x20 } },
4613 SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame){ nsGkAtoms::mfrac_, { NS_NewMathMLmfracFrame, 0x8 | 0x10 | 0x20
} }
,
4614 SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4615 SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msub_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4616 SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msubsup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 |
0x10 | 0x20 } }
,
4617 SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munder_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4618 SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::mover_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4619 SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munderover_, { NS_NewMathMLmunderoverFrame, 0x8 |
0x10 | 0x20 } }
,
4620 SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmrowFrame){ nsGkAtoms::mphantom_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
,
4621 SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame){ nsGkAtoms::mpadded_, { NS_NewMathMLmpaddedFrame, 0x8 | 0x10
| 0x20 } }
,
4622 SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame){ nsGkAtoms::mspace_, { NS_NewMathMLmspaceFrame, 0x8 | 0x10 |
0x20 } }
,
4623 SIMPLE_MATHML_CREATE(none, NS_NewMathMLmrowFrame){ nsGkAtoms::none, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4624 SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmrowFrame){ nsGkAtoms::mprescripts_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4625 SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmrowFrame){ nsGkAtoms::mfenced_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4626 SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::mmultiscripts_, { NS_NewMathMLmmultiscriptsFrame
, 0x8 | 0x10 | 0x20 } }
,
4627 SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame){ nsGkAtoms::mstyle_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4628 SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame){ nsGkAtoms::msqrt_, { NS_NewMathMLmsqrtFrame, 0x8 | 0x10 | 0x20
} }
,
4629 SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame){ nsGkAtoms::mroot_, { NS_NewMathMLmrootFrame, 0x8 | 0x10 | 0x20
} }
,
4630 SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmrowFrame){ nsGkAtoms::maction_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4631 SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame){ nsGkAtoms::mrow_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4632 SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame){ nsGkAtoms::merror_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4633 SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame){ nsGkAtoms::menclose_, { NS_NewMathMLmencloseFrame, 0x8 | 0x10
| 0x20 } }
,
4634 SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLmrowFrame){ nsGkAtoms::semantics_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
};
4635
4636 return FindDataByTag(aElement, aStyle, sMathMLData, ArrayLength(sMathMLData));
4637}
4638
4639nsContainerFrame* nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
4640 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4641 nsContainerFrame* aParentFrame, nsFrameList& aFrameList,
4642 ContainerFrameCreationFunc aConstructor,
4643 ContainerFrameCreationFunc aInnerConstructor, PseudoStyleType aInnerPseudo,
4644 bool aCandidateRootFrame) {
4645 nsIContent* const content = aItem.mContent;
4646 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4647
4648 // Create the outer frame:
4649 nsContainerFrame* newFrame = aConstructor(mPresShell, computedStyle);
4650
4651 InitAndRestoreFrame(aState, content,
4652 aCandidateRootFrame
4653 ? aState.GetGeometricParent(
4654 *computedStyle->StyleDisplay(), aParentFrame)
4655 : aParentFrame,
4656 newFrame);
4657 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4658
4659 // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
4660 RefPtr<ComputedStyle> scForAnon =
4661 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(aInnerPseudo,
4662 computedStyle);
4663
4664 // Create the anonymous inner wrapper frame
4665 nsContainerFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
4666
4667 InitAndRestoreFrame(aState, content, newFrame, innerFrame);
4668
4669 // Put the newly created frames into the right child list
4670 SetInitialSingleChild(newFrame, innerFrame);
4671
4672 aState.AddChild(newFrame, aFrameList, content, aParentFrame,
4673 aCandidateRootFrame, aCandidateRootFrame);
4674
4675 if (!mRootElementFrame && aCandidateRootFrame) {
4676 mRootElementFrame = newFrame;
4677 }
4678
4679 nsFrameConstructorSaveState floatSaveState;
4680 aState.MaybePushFloatContainingBlock(innerFrame, floatSaveState);
4681
4682 nsFrameList childList;
4683
4684 // Process children
4685 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
4686 ConstructFramesFromItemList(
4687 aState, aItem.mChildItems, innerFrame,
4688 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
4689 } else {
4690 ProcessChildren(aState, content, computedStyle, innerFrame, true, childList,
4691 false);
4692 }
4693
4694 // Set the inner wrapper frame's initial primary list
4695 innerFrame->SetInitialChildList(FrameChildListID::Principal,
4696 std::move(childList));
4697
4698 return newFrame;
4699}
4700
4701nsIFrame* nsCSSFrameConstructor::ConstructOuterSVG(
4702 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4703 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4704 nsFrameList& aFrameList) {
4705 return ConstructFrameWithAnonymousChild(
4706 aState, aItem, aParentFrame, aFrameList, NS_NewSVGOuterSVGFrame,
4707 NS_NewSVGOuterSVGAnonChildFrame, PseudoStyleType::mozSVGOuterSVGAnonChild,
4708 true);
4709}
4710
4711nsIFrame* nsCSSFrameConstructor::ConstructMarker(
4712 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4713 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4714 nsFrameList& aFrameList) {
4715 return ConstructFrameWithAnonymousChild(
4716 aState, aItem, aParentFrame, aFrameList, NS_NewSVGMarkerFrame,
4717 NS_NewSVGMarkerAnonChildFrame, PseudoStyleType::mozSVGMarkerAnonChild,
4718 false);
4719}
4720
4721// Only outer <svg> elements can be floated or positioned. All other SVG
4722// should be in-flow.
4723#define SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
\
4724 FrameConstructionData(ToCreationFunc(_func)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
_func(aPs, aStyle); }
, \
4725 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4726 FCDATA_SKIP_ABSPOS_PUSH0x200 | \
4727 FCDATA_DISALLOW_GENERATED_CONTENT0x400)
4728#define SIMPLE_SVG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8
| 0x200 | 0x400)}
\
4729 {nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
}
4730
4731/* static */
4732const nsCSSFrameConstructor::FrameConstructionData*
4733nsCSSFrameConstructor::FindSVGData(const Element& aElement,
4734 nsIFrame* aParentFrame,
4735 bool aIsWithinSVGText,
4736 bool aAllowsTextPathChild,
4737 ComputedStyle& aStyle) {
4738 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"
, 4738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsSVGElement()"
")"); do { *((volatile int*)__null) = 4738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4739
4740 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4741 static constexpr FrameConstructionData sContainerData =
4742 SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)
;
4743
4744 bool parentIsSVG = aIsWithinSVGText;
4745 nsIContent* parentContent =
4746 aParentFrame ? aParentFrame->GetContent() : nullptr;
4747
4748 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4749
4750 // XXXbz should this really be based on the tag of the parent frame's content?
4751 // Should it not be based on the type of the parent frame (e.g. whether it's
4752 // an SVG frame)?
4753 if (parentContent) {
4754 // It's not clear whether the SVG spec intends to allow any SVG
4755 // content within svg:foreignObject at all (SVG 1.1, section
4756 // 23.2), but if it does, it better be svg:svg. So given that
4757 // we're allowing it, treat it as a non-SVG parent.
4758 parentIsSVG =
4759 parentContent->IsSVGElement() &&
4760 parentContent->NodeInfo()->NameAtom() != nsGkAtoms::foreignObject;
4761 }
4762
4763 if ((tag != nsGkAtoms::svg && !parentIsSVG) ||
4764 (tag == nsGkAtoms::desc || tag == nsGkAtoms::title ||
4765 tag == nsGkAtoms::metadata)) {
4766 // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
4767 // svg:svg not contained within svg:svg are incorrect, although they
4768 // don't seem to specify error handling. Ignore them, since many of
4769 // our frame classes can't deal. It *may* be that the document
4770 // should at that point be considered in error according to F.2, but
4771 // it's hard to tell.
4772 //
4773 // Style mutation can't change this situation, so don't bother
4774 // adding to the undisplayed content map.
4775 //
4776 // We don't currently handle any UI for desc/title/metadata
4777 return &sSuppressData;
4778 }
4779
4780 // We don't need frames for animation elements
4781 if (aElement.IsSVGAnimationElement()) {
4782 return &sSuppressData;
4783 }
4784
4785 if (tag == nsGkAtoms::svg && !parentIsSVG) {
4786 // We need outer <svg> elements to have an SVGOuterSVGFrame regardless
4787 // of whether they fail conditional processing attributes, since various
4788 // SVG frames assume that one exists. We handle the non-rendering
4789 // of failing outer <svg> element contents like <switch> statements,
4790 // and do the PassesConditionalProcessingTests call in
4791 // SVGOuterSVGFrame::Init.
4792 static constexpr FrameConstructionData sOuterSVGData(
4793 &nsCSSFrameConstructor::ConstructOuterSVG);
4794 return &sOuterSVGData;
4795 }
4796
4797 if (tag == nsGkAtoms::marker) {
4798 static constexpr FrameConstructionData sMarkerSVGData(
4799 &nsCSSFrameConstructor::ConstructMarker);
4800 return &sMarkerSVGData;
4801 }
4802
4803 if (!aElement.PassesConditionalProcessingTests()) {
4804 // Elements with failing conditional processing attributes never get
4805 // rendered. Note that this is not where we select which frame in a
4806 // <switch> to render! That happens in SVGSwitchFrame::PaintSVG.
4807 if (aIsWithinSVGText) {
4808 // SVGTextFrame doesn't handle conditional processing attributes,
4809 // so don't create frames for descendants of <text> with failing
4810 // attributes. We need frames not to be created so that text layout
4811 // is correct.
4812 return &sSuppressData;
4813 }
4814 // If we're not inside <text>, create an SVGContainerFrame (which is a
4815 // frame that doesn't render) so that paint servers can still be referenced,
4816 // even if they live inside an element with failing conditional processing
4817 // attributes.
4818 return &sContainerData;
4819 }
4820
4821 // Ensure that a stop frame is a child of a gradient and that gradients
4822 // can only have stop children.
4823 bool parentIsGradient = aParentFrame && static_cast<SVGGradientFrame*>(
4824 do_QueryFrame(aParentFrame));
4825 bool stop = (tag == nsGkAtoms::stop);
4826 if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
4827 return &sSuppressData;
4828 }
4829
4830 // Prevent bad frame types being children of filters or parents of filter
4831 // primitives. If aParentFrame is null, we know that the frame that will
4832 // be created will be an nsInlineFrame, so it can never be a filter.
4833 bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
4834 if ((parentIsFilter && !aElement.IsSVGFilterPrimitiveElement()) ||
4835 (!parentIsFilter && aElement.IsSVGFilterPrimitiveElement())) {
4836 return &sSuppressData;
4837 }
4838
4839 // Prevent bad frame types being children of filter primitives or parents of
4840 // filter primitive children. If aParentFrame is null, we know that the frame
4841 // that will be created will be an nsInlineFrame, so it can never be a filter
4842 // primitive.
4843 bool parentIsFEContainerFrame =
4844 aParentFrame && aParentFrame->IsSVGFEContainerFrame();
4845 if ((parentIsFEContainerFrame &&
4846 !aElement.IsSVGFilterPrimitiveChildElement()) ||
4847 (!parentIsFEContainerFrame &&
4848 aElement.IsSVGFilterPrimitiveChildElement())) {
4849 return &sSuppressData;
4850 }
4851
4852 // Special cases for text/tspan/textPath, because the kind of frame
4853 // they get depends on the parent frame. We ignore 'a' elements when
4854 // determining the parent, however.
4855 if (aIsWithinSVGText) {
4856 // If aIsWithinSVGText is true, then we know that the "SVG text uses
4857 // CSS frames" pref was true when this SVG fragment was first constructed.
4858 //
4859 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
4860 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
4861 // really know how to deal with it. This kinda sucks. :(
4862 if (aParentFrame && aParentFrame->GetContent() != aElement.GetParent()) {
4863 return &sSuppressData;
4864 }
4865
4866 // We don't use ConstructInline because we want different behavior
4867 // for generated content.
4868 static constexpr FrameConstructionData sTSpanData(
4869 ToCreationFunc(NS_NewInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewInlineFrame(aPs, aStyle); }
,
4870 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_SKIP_ABSPOS_PUSH0x200 |
4871 FCDATA_DISALLOW_GENERATED_CONTENT0x400 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4872 FCDATA_IS_INLINE0x1000 | FCDATA_USE_CHILD_ITEMS0x10000);
4873 if (tag == nsGkAtoms::textPath) {
4874 if (aAllowsTextPathChild) {
4875 return &sTSpanData;
4876 }
4877 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::a) {
4878 return &sTSpanData;
4879 }
4880 return &sSuppressData;
4881 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::textPath) {
4882 return &sSuppressData;
4883 }
4884
4885 static constexpr FrameConstructionDataByTag sSVGData[] = {
4886 SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame){nsGkAtoms::svg, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGInnerSVGFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4887 SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame){nsGkAtoms::g, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4888 SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame){nsGkAtoms::svgSwitch, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGSwitchFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4889 SIMPLE_SVG_CREATE(symbol, NS_NewSVGSymbolFrame){nsGkAtoms::symbol, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGSymbolFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4890 SIMPLE_SVG_CREATE(polygon, NS_NewSVGGeometryFrame){nsGkAtoms::polygon, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4891 SIMPLE_SVG_CREATE(polyline, NS_NewSVGGeometryFrame){nsGkAtoms::polyline, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4892 SIMPLE_SVG_CREATE(circle, NS_NewSVGGeometryFrame){nsGkAtoms::circle, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4893 SIMPLE_SVG_CREATE(ellipse, NS_NewSVGGeometryFrame){nsGkAtoms::ellipse, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4894 SIMPLE_SVG_CREATE(line, NS_NewSVGGeometryFrame){nsGkAtoms::line, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4895 SIMPLE_SVG_CREATE(rect, NS_NewSVGGeometryFrame){nsGkAtoms::rect, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4896 SIMPLE_SVG_CREATE(path, NS_NewSVGGeometryFrame){nsGkAtoms::path, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4897 SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame){nsGkAtoms::defs, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4898 {nsGkAtoms::text,
4899 {NS_NewSVGTextFrame,
4900 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_ALLOW_BLOCK_STYLES0x8000,
4901 PseudoStyleType::mozSVGText}},
4902 {nsGkAtoms::foreignObject,
4903 {ToCreationFunc(NS_NewSVGForeignObjectFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewSVGForeignObjectFrame(aPs, aStyle); }
,
4904 FCDATA_DISALLOW_OUT_OF_FLOW0x8, PseudoStyleType::mozSVGForeignContent}},
4905 SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame){nsGkAtoms::a, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGAFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4906 SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame){nsGkAtoms::linearGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGLinearGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4907 SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame){nsGkAtoms::radialGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGRadialGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4908 SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame){nsGkAtoms::stop, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGStopFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4909 SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame){nsGkAtoms::use, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGUseFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4910 SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame){nsGkAtoms::view, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGViewFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4911 SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame){nsGkAtoms::image, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGImageFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4912 SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame){nsGkAtoms::clipPath, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGClipPathFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4913 SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame){nsGkAtoms::filter, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFilterFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4914 SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame){nsGkAtoms::pattern, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGPatternFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4915 SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame){nsGkAtoms::mask, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGMaskFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4916 SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feDistantLight, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4917 SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::fePointLight, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4918 SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feSpotLight, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4919 SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame){nsGkAtoms::feBlend, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4920 SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feColorMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4921 SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncR, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4922 SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncG, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4923 SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncB, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4924 SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncA, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4925 SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame){nsGkAtoms::feComposite, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4926 SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame){nsGkAtoms::feComponentTransfer, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4927 SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feConvolveMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4928 SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feDiffuseLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4929 SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame){nsGkAtoms::feDisplacementMap, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4930 SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame){nsGkAtoms::feDropShadow, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4931 SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame){nsGkAtoms::feFlood, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4932 SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame){nsGkAtoms::feGaussianBlur, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4933 SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame){nsGkAtoms::feImage, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEImageFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4934 SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame){nsGkAtoms::feMerge, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4935 SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feMergeNode, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4936 SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame){nsGkAtoms::feMorphology, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4937 SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame){nsGkAtoms::feOffset, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4938 SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feSpecularLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4939 SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame){nsGkAtoms::feTile, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4940 SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame){nsGkAtoms::feTurbulence, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
};
4941
4942 const FrameConstructionData* data =
4943 FindDataByTag(aElement, aStyle, sSVGData, ArrayLength(sSVGData));
4944
4945 if (!data) {
4946 data = &sContainerData;
4947 }
4948
4949 return data;
4950}
4951
4952void nsCSSFrameConstructor::AppendPageBreakItem(
4953 nsIContent* aContent, FrameConstructionItemList& aItems) {
4954 RefPtr<ComputedStyle> pseudoStyle =
4955 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
4956 PseudoStyleType::pageBreak);
4957
4958 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"
, 4959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4959; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
4959 "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"
, 4959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4959; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4960
4961 static constexpr FrameConstructionData sPageBreakData(NS_NewPageBreakFrame,
4962 FCDATA_SKIP_FRAMESET0x1);
4963 aItems.AppendItem(this, &sPageBreakData, aContent, pseudoStyle.forget(),
4964 true);
4965}
4966
4967bool nsCSSFrameConstructor::ShouldCreateItemsForChild(
4968 nsFrameConstructorState& aState, nsIContent* aContent,
4969 nsContainerFrame* aParentFrame) {
4970 aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
4971 // XXX the GetContent() != aContent check is needed due to bug 135040.
4972 // Remove it once that's fixed.
4973 if (aContent->GetPrimaryFrame() &&
4974 aContent->GetPrimaryFrame()->GetContent() == aContent &&
4975 !aState.mCreatingExtraFrames) {
4976 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"
, 4978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4977 "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"
, 4978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4978 "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"
, 4978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4978; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4979 return false;
4980 }
4981
4982 // don't create a whitespace frame if aParent doesn't want it
4983 if (!NeedFrameFor(aState, aParentFrame, aContent)) {
4984 return false;
4985 }
4986
4987 // never create frames for comments or PIs
4988 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
4989 return false;
4990 }
4991
4992 return true;
4993}
4994
4995void nsCSSFrameConstructor::AddFrameConstructionItems(
4996 nsFrameConstructorState& aState, nsIContent* aContent,
4997 bool aSuppressWhiteSpaceOptimizations, const ComputedStyle& aParentStyle,
4998 const InsertionPoint& aInsertion, FrameConstructionItemList& aItems,
4999 ItemFlags aFlags) {
5000 nsContainerFrame* parentFrame = aInsertion.mParentFrame;
5001 if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) {
5002 return;
5003 }
5004 if (MOZ_UNLIKELY(aParentStyle.StyleContent()->mContent.IsNone())(__builtin_expect(!!(aParentStyle.StyleContent()->mContent
.IsNone()), 0))
&&
5005 StaticPrefs::layout_css_element_content_none_enabled()) {
5006 return;
5007 }
5008
5009 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5010 auto flags = aFlags + ItemFlag::AllowPageBreak;
5011 if (parentFrame) {
5012 if (parentFrame->IsInSVGTextSubtree()) {
5013 flags += ItemFlag::IsWithinSVGText;
5014 }
5015 if (parentFrame->IsBlockFrame() && parentFrame->GetParent() &&
5016 parentFrame->GetParent()->IsSVGTextFrame()) {
5017 flags += ItemFlag::AllowTextPathChild;
5018 }
5019 }
5020 AddFrameConstructionItemsInternal(aState, aContent, parentFrame,
5021 aSuppressWhiteSpaceOptimizations,
5022 computedStyle, flags, aItems);
5023}
5024
5025// Whether we should suppress frames for a child under a <select> frame.
5026//
5027// Never create frames for non-option/optgroup kids of <select> and non-option
5028// kids of <optgroup> inside a <select>.
5029static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
5030 const nsIContent& aChild) {
5031 if (!aParent ||
5032 !aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup,
5033 nsGkAtoms::option)) {
5034 return false;
5035 }
5036
5037 // Allow native anonymous content no matter what.
5038 if (aChild.IsRootOfNativeAnonymousSubtree()) {
5039 return false;
5040 }
5041
5042 // Options with labels have their label text added in ::before by forms.css.
5043 // Suppress frames for their child text.
5044 if (aParent->IsHTMLElement(nsGkAtoms::option)) {
5045 return aParent->AsElement()->HasNonEmptyAttr(nsGkAtoms::label);
5046 }
5047
5048 // If we're in any display: contents subtree, just suppress the frame.
5049 //
5050 // We can't be regular NAC, since display: contents has no frame to generate
5051 // them off.
5052 if (aChild.GetParent() != aParent) {
5053 return true;
5054 }
5055
5056 // Option is always fine.
5057 if (aChild.IsHTMLElement(nsGkAtoms::option)) {
5058 return false;
5059 }
5060
5061 // <optgroup> is OK in <select> but not in <optgroup>.
5062 if (aChild.IsHTMLElement(nsGkAtoms::optgroup) &&
5063 aParent->IsHTMLElement(nsGkAtoms::select)) {
5064 return false;
5065 }
5066
5067 // Anything else is not ok.
5068 return true;
5069}
5070
5071const nsCSSFrameConstructor::FrameConstructionData*
5072nsCSSFrameConstructor::FindDataForContent(nsIContent& aContent,
5073 ComputedStyle& aStyle,
5074 nsIFrame* aParentFrame,
5075 ItemFlags aFlags) {
5076 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"
, 5078); 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) = 5078; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5077 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"
, 5078); 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) = 5078; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5078 "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"
, 5078); 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) = 5078; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5079
5080 if (auto* text = Text::FromNode(aContent)) {
5081 return FindTextData(*text, aParentFrame);
5082 }
5083
5084 return FindElementData(*aContent.AsElement(), aStyle, aParentFrame, aFlags);
5085}
5086
5087const nsCSSFrameConstructor::FrameConstructionData*
5088nsCSSFrameConstructor::FindElementData(const Element& aElement,
5089 ComputedStyle& aStyle,
5090 nsIFrame* aParentFrame,
5091 ItemFlags aFlags) {
5092 // Don't create frames for non-SVG element children of SVG elements.
5093 if (!aElement.IsSVGElement()) {
5094 if (aParentFrame && IsFrameForSVG(aParentFrame) &&
5095 !aParentFrame->IsSVGForeignObjectFrame()) {
5096 return nullptr;
5097 }
5098 if (aFlags.contains(ItemFlag::IsWithinSVGText)) {
5099 return nullptr;
5100 }
5101 }
5102
5103 if (auto* data = FindElementTagData(aElement, aStyle, aParentFrame, aFlags)) {
5104 return data;
5105 }
5106
5107 // Check for 'content: <image-url>' on the element (which makes us ignore
5108 // 'display' values other than 'none' or 'contents').
5109 if (nsImageFrame::ShouldCreateImageFrameForContentProperty(aElement,
5110 aStyle)) {
5111 static constexpr FrameConstructionData sImgData(
5112 NS_NewImageFrameForContentProperty);
5113 return &sImgData;
5114 }
5115
5116 const bool shouldBlockify = aFlags.contains(ItemFlag::IsForRenderedLegend) ||
5117 aFlags.contains(ItemFlag::IsForOutsideMarker);
5118 if (shouldBlockify && !aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
5119 // Make a temp copy of StyleDisplay and blockify its mDisplay value.
5120 auto display = *aStyle.StyleDisplay();
5121 bool isRootElement = false;
5122 uint16_t rawDisplayValue =
5123 Servo_ComputedValues_BlockifiedDisplay(&aStyle, isRootElement);
5124 display.mDisplay = StyleDisplay{rawDisplayValue};
5125 return FindDisplayData(display, aElement);
5126 }
5127
5128 const auto& display = *aStyle.StyleDisplay();
5129 return FindDisplayData(display, aElement);
5130}
5131
5132const nsCSSFrameConstructor::FrameConstructionData*
5133nsCSSFrameConstructor::FindElementTagData(const Element& aElement,
5134 ComputedStyle& aStyle,
5135 nsIFrame* aParentFrame,
5136 ItemFlags aFlags) {
5137 switch (aElement.GetNameSpaceID()) {
5138 case kNameSpaceID_XHTML3:
5139 return FindHTMLData(aElement, aParentFrame, aStyle);
5140 case kNameSpaceID_MathML6:
5141 return FindMathMLData(aElement, aStyle);
5142 case kNameSpaceID_SVG9:
5143 return FindSVGData(aElement, aParentFrame,
5144 aFlags.contains(ItemFlag::IsWithinSVGText),
5145 aFlags.contains(ItemFlag::AllowTextPathChild), aStyle);
5146 case kNameSpaceID_XUL8:
5147 return FindXULTagData(aElement, aStyle);
5148 default:
5149 return nullptr;
5150 }
5151}
5152
5153void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
5154 nsFrameConstructorState& aState, nsIContent* aContent,
5155 nsContainerFrame* aParentFrame, bool aSuppressWhiteSpaceOptimizations,
5156 ComputedStyle* aComputedStyle, ItemFlags aFlags,
5157 FrameConstructionItemList& aItems) {
5158 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"
, 5159); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5159; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5159 "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"
, 5159); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5159; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5160 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"
, 5160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsInComposedDoc()"
")"); do { *((volatile int*)__null) = 5160; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5161 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"
, 5162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5162 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"
, 5162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5163
5164 const bool withinSVGText = aFlags.contains(ItemFlag::IsWithinSVGText);
5165 const bool isGeneratedContent = aFlags.contains(ItemFlag::IsGeneratedContent);
5166 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"
, 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5167; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5167 "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"
, 5167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5167; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5168
5169 FrameConstructionItem* item = nullptr;
5170 auto cleanupGeneratedContent = mozilla::MakeScopeExit([&]() {
5171 if (isGeneratedContent && !item) {
5172 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"
, 5174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5174; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5173 "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"
, 5174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5174; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5174 "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"
, 5174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5174; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5175 aContent->UnbindFromTree();
5176 }
5177 });
5178
5179 // 'display:none' elements never creates any frames at all.
5180 const nsStyleDisplay& display = *aComputedStyle->StyleDisplay();
5181 if (display.mDisplay == StyleDisplay::None) {
5182 return;
5183 }
5184
5185 if (display.mDisplay == StyleDisplay::Contents) {
5186 // See the mDisplay fixup code in StyleAdjuster::adjust.
5187 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"
, 5188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5188; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5188 "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"
, 5188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5188; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5189
5190 // FIXME(bug 1588477): <svg:text>'s TextNodeCorrespondenceRecorder has
5191 // trouble with everything that looks like display: contents.
5192 if (withinSVGText) {
5193 return;
5194 }
5195
5196 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5197 *aComputedStyle, PseudoStyleType::before,
5198 aItems);
5199
5200 FlattenedChildIterator iter(aContent);
5201 InsertionPoint insertion(aParentFrame, aContent);
5202 for (nsIContent* child = iter.GetNextChild(); child;
5203 child = iter.GetNextChild()) {
5204 AddFrameConstructionItems(aState, child, aSuppressWhiteSpaceOptimizations,
5205 *aComputedStyle, insertion, aItems, aFlags);
5206 }
5207 aItems.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
5208
5209 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5210 *aComputedStyle, PseudoStyleType::after, aItems);
5211 return;
5212 }
5213
5214 nsIContent* parent = aParentFrame ? aParentFrame->GetContent() : nullptr;
5215 if (ShouldSuppressFrameInSelect(parent, *aContent)) {
5216 return;
5217 }
5218
5219 if (aContent->IsHTMLElement(nsGkAtoms::legend) && aParentFrame) {
5220 const nsFieldSetFrame* const fs = GetFieldSetFrameFor(aParentFrame);
5221 if (fs && !fs->GetLegend() && !aState.mHasRenderedLegend &&
5222 !aComputedStyle->StyleDisplay()->IsFloatingStyle() &&
5223 !aComputedStyle->StyleDisplay()->IsAbsolutelyPositionedStyle()) {
5224 aState.mHasRenderedLegend = true;
5225 aFlags += ItemFlag::IsForRenderedLegend;
5226 }
5227 }
5228
5229 const FrameConstructionData* const data =
5230 FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
5231 if (!data || data->mBits & FCDATA_SUPPRESS_FRAME0x40) {
5232 return;
5233 }
5234
5235 const bool isPopup = data->mBits & FCDATA_IS_POPUP0x100;
5236
5237 const uint32_t bits = data->mBits;
5238
5239 // Inside colgroups, suppress everything except columns.
5240 if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
5241 (!(bits & FCDATA_IS_TABLE_PART0x800) ||
5242 display.mDisplay != StyleDisplay::TableColumn)) {
5243 return;
5244 }
5245
5246 const bool canHavePageBreak =
5247 aFlags.contains(ItemFlag::AllowPageBreak) &&
5248 aState.mPresContext->IsPaginated() &&
5249 !display.IsAbsolutelyPositionedStyle() &&
5250 !(aParentFrame && aParentFrame->IsFlexOrGridContainer()) &&
5251 !(bits & FCDATA_IS_TABLE_PART0x800) && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5252 if (canHavePageBreak && display.BreakBefore()) {
5253 AppendPageBreakItem(aContent, aItems);
5254 }
5255
5256 if (!item) {
5257 item = aItems.AppendItem(this, data, aContent, do_AddRef(aComputedStyle),
5258 aSuppressWhiteSpaceOptimizations);
5259 if (aFlags.contains(ItemFlag::IsForRenderedLegend)) {
5260 item->mIsRenderedLegend = true;
5261 }
5262 }
5263 item->mIsText = !aContent->IsElement();
5264 item->mIsGeneratedContent = isGeneratedContent;
5265 if (isGeneratedContent) {
5266 // We need to keep this alive until the frame takes ownership.
5267 // This corresponds to the Release in ConstructFramesFromItem.
5268 item->mContent->AddRef();
5269 }
5270 item->mIsPopup = isPopup;
5271
5272 if (canHavePageBreak && display.BreakAfter()) {
5273 AppendPageBreakItem(aContent, aItems);
5274 }
5275
5276 if (bits & FCDATA_IS_INLINE0x1000) {
5277 // To correctly set item->mIsAllInline we need to build up our child items
5278 // right now.
5279 BuildInlineChildItems(aState, *item,
5280 aFlags.contains(ItemFlag::IsWithinSVGText),
5281 aFlags.contains(ItemFlag::AllowTextPathChild));
5282 item->mIsBlock = false;
5283 } else {
5284 // Compute a boolean isInline which is guaranteed to be false for blocks
5285 // (but may also be false for some inlines).
5286 const bool isInline =
5287 // Table-internal things are inline-outside if and only if they're kids
5288 // of inlines, since they'll trigger construction of inline-table
5289 // pseudos.
5290 ((bits & FCDATA_IS_TABLE_PART0x800) &&
5291 (!aParentFrame || // No aParentFrame means inline
5292 aParentFrame->StyleDisplay()->IsInlineFlow())) ||
5293 // Things that are inline-outside but aren't inline frames are inline
5294 display.IsInlineOutsideStyle() ||
5295 // Popups that are certainly out of flow.
5296 isPopup;
5297
5298 // Set mIsAllInline conservatively. It just might be that even an inline
5299 // that has mIsAllInline false doesn't need an {ib} split. So this is just
5300 // an optimization to keep from doing too much work in cases when we can
5301 // show that mIsAllInline is true..
5302 item->mIsAllInline =
5303 isInline ||
5304 // Figure out whether we're guaranteed this item will be out of flow.
5305 // This is not a precise test, since one of our ancestor inlines might
5306 // add an absolute containing block (if it's relatively positioned) when
5307 // there wasn't such a containing block before. But it's conservative
5308 // in the sense that anything that will really end up as an in-flow
5309 // non-inline will test false here. In other words, if this test is
5310 // true we're guaranteed to be inline; if it's false we don't know what
5311 // we'll end up as.
5312 //
5313 // If we make this test precise, we can remove some of the code dealing
5314 // with the imprecision in ConstructInline and adjust the comments on
5315 // mIsAllInline and mIsBlock in the header.
5316 (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
5317 aState.GetGeometricParent(display, nullptr));
5318
5319 // Set mIsBlock conservatively. It's OK to set it false for some real
5320 // blocks, but not OK to set it true for things that aren't blocks. Since
5321 // isOutOfFlow might be false even in cases when the frame will end up
5322 // out-of-flow, we can't use it here. But we _can_ say that the frame will
5323 // for sure end up in-flow if it's not floated or absolutely positioned.
5324 item->mIsBlock = !isInline && !display.IsAbsolutelyPositionedStyle() &&
5325 !display.IsFloatingStyle() && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5326 }
5327
5328 if (item->mIsAllInline) {
5329 aItems.InlineItemAdded();
5330 } else if (item->mIsBlock) {
5331 aItems.BlockItemAdded();
5332 }
5333}
5334
5335/**
5336 * Return true if the frame construction item pointed to by aIter will
5337 * create a frame adjacent to a line boundary in the frame tree, and that
5338 * line boundary is induced by a content node adjacent to the frame's
5339 * content node in the content tree. The latter condition is necessary so
5340 * that ContentAppended/ContentInserted/ContentRemoved can easily find any
5341 * text nodes that were suppressed here.
5342 */
5343bool nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter) {
5344 if (aIter.item().mSuppressWhiteSpaceOptimizations) {
5345 return false;
5346 }
5347
5348 if (aIter.AtStart()) {
5349 if (aIter.List()->HasLineBoundaryAtStart() &&
5350 !aIter.item().mContent->GetPreviousSibling())
5351 return true;
5352 } else {
5353 FCItemIterator prev = aIter;
5354 prev.Prev();
5355 if (prev.item().IsLineBoundary() &&
5356 !prev.item().mSuppressWhiteSpaceOptimizations &&
5357 aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
5358 return true;
5359 }
5360
5361 FCItemIterator next = aIter;
5362 next.Next();
5363 if (next.IsDone()) {
5364 if (aIter.List()->HasLineBoundaryAtEnd() &&
5365 !aIter.item().mContent->GetNextSibling())
5366 return true;
5367 } else {
5368 if (next.item().IsLineBoundary() &&
5369 !next.item().mSuppressWhiteSpaceOptimizations &&
5370 aIter.item().mContent->GetNextSibling() == next.item().mContent)
5371 return true;
5372 }
5373
5374 return false;
5375}
5376
5377void nsCSSFrameConstructor::ConstructFramesFromItem(
5378 nsFrameConstructorState& aState, FCItemIterator& aIter,
5379 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
5380 FrameConstructionItem& item = aIter.item();
5381 ComputedStyle* computedStyle = item.mComputedStyle;
5382 if (item.mIsText) {
5383 // If this is collapsible whitespace next to a line boundary,
5384 // don't create a frame. item.IsWhitespace() also sets the
5385 // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
5386 // end up creating a frame, nsTextFrame::Init will clear the flag.)
5387 // We don't do this for generated content, because some generated
5388 // text content is empty text nodes that are about to be initialized.
5389 // (We check mAdditionalStateBits because only the generated content
5390 // container's frame construction item is marked with
5391 // mIsGeneratedContent, and we might not have an aParentFrame.)
5392 // We don't do it for content that may have Shadow DOM siblings / insertion
5393 // points, because they make it difficult to correctly create the frame due
5394 // to dynamic changes.
5395 // We don't do it for SVG text, since we might need to position and
5396 // measure the white space glyphs due to x/y/dx/dy attributes.
5397 if (AtLineBoundary(aIter) &&
5398 !computedStyle->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
5399 aIter.List()->ParentHasNoShadowDOM() &&
5400 !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
5401 (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) &&
5402 !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT0x80000) &&
5403 !mAlwaysCreateFramesForIgnorableWhitespace && item.IsWhitespace(aState))
5404 return;
5405
5406 ConstructTextFrame(item.mFCData, aState, item.mContent, aParentFrame,
5407 computedStyle, aFrameList);
5408 return;
5409 }
5410
5411 AutoRestore<nsFrameState> savedStateBits(aState.mAdditionalStateBits);
5412 if (item.mIsGeneratedContent) {
5413 // Ensure that frames created here are all tagged with
5414 // NS_FRAME_GENERATED_CONTENT.
5415 aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
5416 }
5417
5418 // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
5419 ConstructFrameFromItemInternal(item, aState, aParentFrame, aFrameList);
5420
5421 if (item.mIsGeneratedContent) {
5422 // This corresponds to the AddRef in AddFrameConstructionItemsInternal.
5423 // The frame owns the generated content now.
5424 item.mContent->Release();
5425
5426 // Now that we've passed ownership of item.mContent to the frame, unset
5427 // our generated content flag so we don't release or unbind it ourselves.
5428 item.mIsGeneratedContent = false;
5429 }
5430}
5431
5432nsContainerFrame* nsCSSFrameConstructor::GetAbsoluteContainingBlock(
5433 nsIFrame* aFrame, ContainingBlockType aType) {
5434 // Starting with aFrame, look for a frame that is absolutely positioned or
5435 // relatively positioned (and transformed, if aType is FIXED)
5436 for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
5437 if (frame->IsMathMLFrame()) {
5438 // If it's mathml, bail out -- no absolute positioning out from inside
5439 // mathml frames. Note that we don't make this part of the loop
5440 // condition because of the stuff at the end of this method...
5441 return nullptr;
5442 }
5443
5444 // Look for the ICB.
5445 if (aType == FIXED_POS) {
5446 LayoutFrameType t = frame->Type();
5447 if (t == LayoutFrameType::Viewport || t == LayoutFrameType::PageContent) {
5448 return static_cast<nsContainerFrame*>(frame);
5449 }
5450 }
5451
5452 // If the frame is positioned, we will probably return it as the containing
5453 // block (see the exceptions below). Otherwise, we'll start looking at the
5454 // parent frame, unless we're dealing with a scrollframe.
5455 // Scrollframes are special since they're not positioned, but their
5456 // scrolledframe might be. So, we need to check this special case to return
5457 // the correct containing block (the scrolledframe) in that case.
5458 // If we're looking for a fixed-pos containing block and the frame is
5459 // not transformed, skip it.
5460 if (!frame->IsAbsPosContainingBlock()) {
5461 continue;
5462 }
5463 if (aType == FIXED_POS && !frame->IsFixedPosContainingBlock()) {
5464 continue;
5465 }
5466 nsIFrame* absPosCBCandidate = frame;
5467 LayoutFrameType type = absPosCBCandidate->Type();
5468 if (type == LayoutFrameType::FieldSet) {
5469 absPosCBCandidate =
5470 static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
5471 if (!absPosCBCandidate) {
5472 continue;
5473 }
5474 type = absPosCBCandidate->Type();
5475 }
5476 if (type == LayoutFrameType::ScrollContainer) {
5477 ScrollContainerFrame* scrollContainerFrame =
5478 do_QueryFrame(absPosCBCandidate);
5479 absPosCBCandidate = scrollContainerFrame->GetScrolledFrame();
5480 if (!absPosCBCandidate) {
5481 continue;
5482 }
5483 type = absPosCBCandidate->Type();
5484 }
5485 // Only first continuations can be containing blocks.
5486 absPosCBCandidate = absPosCBCandidate->FirstContinuation();
5487 // Is the frame really an absolute container?
5488 if (!absPosCBCandidate->IsAbsoluteContainer()) {
5489 continue;
5490 }
5491
5492 // For tables, skip the inner frame and consider the table wrapper frame.
5493 if (type == LayoutFrameType::Table) {
5494 continue;
5495 }
5496 // For table wrapper frames, we can just return absPosCBCandidate.
5497 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"
, 5498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5498; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5498 "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"
, 5498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5498; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5499 return static_cast<nsContainerFrame*>(absPosCBCandidate);
5500 }
5501
5502 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"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aType != FIXED_POS"
") (" "no ICB in this frame tree?" ")"); do { *((volatile int
*)__null) = 5502; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5503
5504 // It is possible for the search for the containing block to fail, because
5505 // no absolute container can be found in the parent chain. In those cases,
5506 // we fall back to the document element's containing block.
5507 return mDocElementContainingBlock;
5508}
5509
5510nsContainerFrame* nsCSSFrameConstructor::GetFloatContainingBlock(
5511 nsIFrame* aFrame) {
5512 // Starting with aFrame, look for a frame that is a float containing block.
5513 // If we hit a frame which prevents its descendants from floating, bail out.
5514 // The logic here needs to match the logic in MaybePushFloatContainingBlock().
5515 for (nsIFrame* containingBlock = aFrame;
5516 containingBlock && !ShouldSuppressFloatingOfDescendants(containingBlock);
5517 containingBlock = containingBlock->GetParent()) {
5518 if (containingBlock->IsFloatContainingBlock()) {
5519 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"
, 5520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5520 "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"
, 5520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5521 return static_cast<nsContainerFrame*>(containingBlock);
5522 }
5523 }
5524
5525 // If we didn't find a containing block, then there just isn't
5526 // one.... return null
5527 return nullptr;
5528}
5529
5530/**
5531 * This function will get the previous sibling to use for an append operation.
5532 *
5533 * It takes a parent frame (must not be null) and the next insertion sibling, if
5534 * the parent content is display: contents or has ::after content (may be null).
5535 */
5536static nsIFrame* FindAppendPrevSibling(nsIFrame* aParentFrame,
5537 nsIFrame* aNextSibling) {
5538 aParentFrame->DrainSelfOverflowList();
5539
5540 if (aNextSibling) {
5541 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"
, 5543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5543
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5542 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"
, 5543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5543
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5543 "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"
, 5543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5543
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5544 return aNextSibling->GetPrevSibling();
5545 }
5546
5547 return aParentFrame->PrincipalChildList().LastChild();
5548}
5549
5550/**
5551 * Finds the right parent frame to append content to aParentFrame.
5552 *
5553 * Cannot return or receive null.
5554 */
5555static nsContainerFrame* ContinuationToAppendTo(
5556 nsContainerFrame* aParentFrame) {
5557 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"
, 5557); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 5557; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5558
5559 if (IsFramePartOfIBSplit(aParentFrame)) {
5560 // If the frame we are manipulating is a ib-split frame (that is, one that's
5561 // been created as a result of a block-in-inline situation) then we need to
5562 // append to the last ib-split sibling, not to the frame itself.
5563 //
5564 // Always make sure to look at the last continuation of the frame for the
5565 // {ib} case, even if that continuation is empty.
5566 //
5567 // We don't do this for the non-ib-split-frame case, since in the other
5568 // cases appending to the last nonempty continuation is fine and in fact not
5569 // doing that can confuse code that doesn't know to pull kids from
5570 // continuations other than its next one.
5571 return static_cast<nsContainerFrame*>(
5572 GetLastIBSplitSibling(aParentFrame)->LastContinuation());
5573 }
5574
5575 return nsLayoutUtils::LastContinuationWithChild(aParentFrame);
5576}
5577
5578/**
5579 * This function will get the next sibling for a frame insert operation given
5580 * the parent and previous sibling. aPrevSibling may be null.
5581 */
5582static nsIFrame* GetInsertNextSibling(nsIFrame* aParentFrame,
5583 nsIFrame* aPrevSibling) {
5584 if (aPrevSibling) {
5585 return aPrevSibling->GetNextSibling();
5586 }
5587
5588 return aParentFrame->PrincipalChildList().FirstChild();
5589}
5590
5591void nsCSSFrameConstructor::AppendFramesToParent(
5592 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
5593 nsFrameList& aFrameList, nsIFrame* aPrevSibling, bool aIsRecursiveCall) {
5594 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"
, 5597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5595 !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"
, 5597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5596 !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"
, 5597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5597 "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"
, 5597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5598 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"
, 5599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5599; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5599 "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"
, 5599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5599; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5600 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"
, 5604); 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
) = 5604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5601 !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"
, 5604); 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
) = 5604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5602 !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"
, 5604); 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
) = 5604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5603 "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"
, 5604); 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
) = 5604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5604 "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"
, 5604); 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
) = 5604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
5605
5606 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
5607
5608 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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
5609 !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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
5610 ->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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
5611 .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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
5612 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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
5613 "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"
, 5613); MOZ_PretendNoReturn(); } } while (0)
;
5614 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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
5615 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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
5616 (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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
5617 !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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
5618 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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
5619 "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"
, 5619); MOZ_PretendNoReturn(); } } while (0)
;
5620
5621 // If we're inserting a list of frames at the end of the trailing inline
5622 // of an {ib} split, we may need to create additional {ib} siblings to parent
5623 // them.
5624 if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
5625 // When we get here, our frame list might start with a block. If it does
5626 // so, and aParentFrame is an inline, and it and all its previous
5627 // continuations have no siblings, then put the initial blocks from the
5628 // frame list into the previous block of the {ib} split. Note that we
5629 // didn't want to stop at the block part of the split when figuring out
5630 // initial parent, because that could screw up float parenting; it's easier
5631 // to do this little fixup here instead.
5632 if (aFrameList.NotEmpty() && aFrameList.FirstChild()->IsBlockOutside()) {
5633 // See whether our trailing inline is empty
5634 nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
5635 if (firstContinuation->PrincipalChildList().IsEmpty()) {
5636 // Our trailing inline is empty. Collect our starting blocks from
5637 // aFrameList, get the right parent frame for them, and put them in.
5638 nsFrameList blockKids =
5639 aFrameList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
5640 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"
, 5640); MOZ_PretendNoReturn(); } } while (0)
;
5641
5642 nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
5643 prevBlock =
5644 static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
5645 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"
, 5645); MOZ_PretendNoReturn(); } } while (0)
;
5646
5647 MoveChildrenTo(aParentFrame, prevBlock, blockKids);
5648 }
5649 }
5650
5651 // We want to put some of the frames into this inline frame.
5652 nsFrameList inlineKids =
5653 aFrameList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
5654
5655 if (!inlineKids.IsEmpty()) {
5656 AppendFrames(aParentFrame, FrameChildListID::Principal,
5657 std::move(inlineKids));
5658 }
5659
5660 if (!aFrameList.IsEmpty()) {
5661 nsFrameList ibSiblings;
5662 CreateIBSiblings(aState, aParentFrame,
5663 aParentFrame->IsAbsPosContainingBlock(), aFrameList,
5664 ibSiblings);
5665
5666 // Make sure to trigger reflow of the inline that used to be our
5667 // last one and now isn't anymore, since its GetSkipSides() has
5668 // changed.
5669 mPresShell->FrameNeedsReflow(aParentFrame,
5670 IntrinsicDirty::FrameAndAncestors,
5671 NS_FRAME_HAS_DIRTY_CHILDREN);
5672
5673 // Recurse so we create new ib siblings as needed for aParentFrame's
5674 // parent
5675 return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
5676 aParentFrame, true);
5677 }
5678 return;
5679 }
5680
5681 // If we're appending a list of frames to the last continuations of a
5682 // ::-moz-column-content, we may need to create column-span siblings for them.
5683 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
5684 // Extract any initial non-column-span kids, and append them to
5685 // ::-moz-column-content's child list.
5686 nsFrameList initialNonColumnSpanKids =
5687 aFrameList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
5688 AppendFrames(aParentFrame, FrameChildListID::Principal,
5689 std::move(initialNonColumnSpanKids));
5690
5691 if (aFrameList.IsEmpty()) {
5692 // No more kids to process (there weren't any column-span kids).
5693 return;
5694 }
5695
5696 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
5697 aState, aParentFrame, aFrameList,
5698 // Column content should never be a absolute/fixed positioned containing
5699 // block. Pass nullptr as aPositionedFrame.
5700 nullptr);
5701
5702 nsContainerFrame* columnSetWrapper = aParentFrame->GetParent();
5703 while (!columnSetWrapper->IsColumnSetWrapperFrame()) {
5704 columnSetWrapper = columnSetWrapper->GetParent();
5705 }
5706 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"
, 5707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5707 "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"
, 5707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5708
5709 FinishBuildingColumns(aState, columnSetWrapper, aParentFrame,
5710 columnSpanSiblings);
5711
5712 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"
, 5713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5713; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5713 "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"
, 5713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5713; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5714 return;
5715 }
5716
5717 // Insert the frames after our aPrevSibling
5718 InsertFrames(aParentFrame, FrameChildListID::Principal, aPrevSibling,
5719 std::move(aFrameList));
5720}
5721
5722// This gets called to see if the frames corresponding to aSibling and aContent
5723// should be siblings in the frame tree. Although (1) rows and cols, (2) row
5724// groups and col groups, (3) row groups and captions, (4) legends and content
5725// inside fieldsets, (5) popups and other kids of the menu are siblings from a
5726// content perspective, they are not considered siblings in the frame tree.
5727bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
5728 nsIContent* aContent,
5729 Maybe<StyleDisplay>& aDisplay) {
5730 StyleDisplay siblingDisplay = aSibling->GetDisplay();
5731 if (StyleDisplay::TableColumnGroup == siblingDisplay ||
5732 StyleDisplay::TableColumn == siblingDisplay ||
5733 StyleDisplay::TableCaption == siblingDisplay ||
5734 StyleDisplay::TableHeaderGroup == siblingDisplay ||
5735 StyleDisplay::TableRowGroup == siblingDisplay ||
5736 StyleDisplay::TableFooterGroup == siblingDisplay) {
5737 // if we haven't already, resolve a style to find the display type of
5738 // aContent.
5739 if (aDisplay.isNothing()) {
5740 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
5741 // Comments and processing instructions never have frames, so we should
5742 // not try to generate styles for them.
5743 return false;
5744 }
5745 // FIXME(emilio): This is buggy some times, see bug 1424656.
5746 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5747 const nsStyleDisplay* display = computedStyle->StyleDisplay();
5748 aDisplay.emplace(display->mDisplay);
5749 }
5750
5751 StyleDisplay display = aDisplay.value();
5752 // To have decent performance we want to return false in cases in which
5753 // reordering the two siblings has no effect on display. To ensure
5754 // correctness, we MUST return false in cases where the two siblings have
5755 // the same desired parent type and live on different display lists.
5756 // Specificaly, columns and column groups should only consider columns and
5757 // column groups as valid siblings. Captions should only consider other
5758 // captions. All other things should consider each other as valid
5759 // siblings. The restriction in the |if| above on siblingDisplay is ok,
5760 // because for correctness the only part that really needs to happen is to
5761 // not consider captions, column groups, and row/header/footer groups
5762 // siblings of each other. Treating a column or colgroup as a valid
5763 // sibling of a non-table-related frame will just mean we end up reframing.
5764 if ((siblingDisplay == StyleDisplay::TableCaption) !=
5765 (display == StyleDisplay::TableCaption)) {
5766 // One's a caption and the other is not. Not valid siblings.
5767 return false;
5768 }
5769
5770 if ((siblingDisplay == StyleDisplay::TableColumnGroup ||
5771 siblingDisplay == StyleDisplay::TableColumn) !=
5772 (display == StyleDisplay::TableColumnGroup ||
5773 display == StyleDisplay::TableColumn)) {
5774 // One's a column or column group and the other is not. Not valid
5775 // siblings.
5776 return false;
5777 }
5778 // Fall through; it's possible that the display type was overridden and
5779 // a different sort of frame was constructed, so we may need to return false
5780 // below.
5781 }
5782
5783 return true;
5784}
5785
5786// FIXME(emilio): If we ever kill IsValidSibling() we can simplify this quite a
5787// bit (no need to pass aTargetContent or aTargetContentDisplay, and the
5788// adjust() calls can be responsibility of the caller).
5789template <nsCSSFrameConstructor::SiblingDirection aDirection>
5790nsIFrame* nsCSSFrameConstructor::FindSiblingInternal(
5791 FlattenedChildIterator& aIter, nsIContent* aTargetContent,
5792 Maybe<StyleDisplay>& aTargetContentDisplay) {
5793 auto adjust = [&](nsIFrame* aPotentialSiblingFrame) -> nsIFrame* {
5794 return AdjustSiblingFrame(aPotentialSiblingFrame, aTargetContent,
5795 aTargetContentDisplay, aDirection);
5796 };
5797
5798 auto nextDomSibling = [](FlattenedChildIterator& aIter) -> nsIContent* {
5799 return aDirection == SiblingDirection::Forward ? aIter.GetNextChild()
5800 : aIter.GetPreviousChild();
5801 };
5802
5803 auto getInsideMarkerFrame = [](const nsIContent* aContent) -> nsIFrame* {
5804 auto* marker = nsLayoutUtils::GetMarkerFrame(aContent);
5805 const bool isInsideMarker =
5806 marker && marker->GetInFlowParent()->StyleList()->mListStylePosition ==
5807 StyleListStylePosition::Inside;
5808 return isInsideMarker ? marker : nullptr;
5809 };
5810
5811 auto getNearPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5812 if (aDirection == SiblingDirection::Forward) {
5813 if (auto* marker = getInsideMarkerFrame(aContent)) {
5814 return marker;
5815 }
5816 return nsLayoutUtils::GetBeforeFrame(aContent);
5817 }
5818 return nsLayoutUtils::GetAfterFrame(aContent);
5819 };
5820
5821 auto getFarPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5822 if (aDirection == SiblingDirection::Forward) {
5823 return nsLayoutUtils::GetAfterFrame(aContent);
5824 }
5825 if (auto* before = nsLayoutUtils::GetBeforeFrame(aContent)) {
5826 return before;
5827 }
5828 return getInsideMarkerFrame(aContent);
5829 };
5830
5831 while (nsIContent* sibling = nextDomSibling(aIter)) {
5832 // NOTE(emilio): It's important to check GetPrimaryFrame() before
5833 // IsDisplayContents to get the correct insertion point when multiple
5834 // siblings go from display: non-none to display: contents.
5835 if (nsIFrame* primaryFrame = sibling->GetPrimaryFrame()) {
5836 // XXX the GetContent() == sibling check is needed due to bug 135040.
5837 // Remove it once that's fixed.
5838 if (primaryFrame->GetContent() == sibling) {
5839 if (nsIFrame* frame = adjust(primaryFrame)) {
5840 return frame;
5841 }
5842 }
5843 }
5844
5845 if (IsDisplayContents(sibling)) {
5846 if (nsIFrame* frame = adjust(getNearPseudo(sibling))) {
5847 return frame;
5848 }
5849
5850 const bool startFromBeginning = aDirection == SiblingDirection::Forward;
5851 FlattenedChildIterator iter(sibling, startFromBeginning);
5852 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5853 iter, aTargetContent, aTargetContentDisplay);
5854 if (sibling) {
5855 return sibling;
5856 }
5857 }
5858 }
5859
5860 return adjust(getFarPseudo(aIter.Parent()));
5861}
5862
5863nsIFrame* nsCSSFrameConstructor::AdjustSiblingFrame(
5864 nsIFrame* aSibling, nsIContent* aTargetContent,
5865 Maybe<StyleDisplay>& aTargetContentDisplay, SiblingDirection aDirection) {
5866 if (!aSibling) {
5867 return nullptr;
5868 }
5869
5870 if (aSibling->IsRenderedLegend()) {
5871 return nullptr;
5872 }
5873
5874 if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
5875 aSibling = aSibling->GetPlaceholderFrame();
5876 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"
, 5876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSibling" ")"
); do { *((volatile int*)__null) = 5876; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5877 }
5878
5879 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"
, 5879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aSibling->GetPrevContinuation()"
") (" "How?" ")"); do { *((volatile int*)__null) = 5879; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5880 if (aDirection == SiblingDirection::Backward) {
5881 // The frame may be a ib-split frame (a split inline frame that contains a
5882 // block). Get the last part of that split.
5883 if (IsFramePartOfIBSplit(aSibling)) {
5884 aSibling = GetLastIBSplitSibling(aSibling);
5885 }
5886
5887 // The frame may have a continuation. If so, we want the last
5888 // non-overflow-container continuation as our previous sibling.
5889 aSibling = aSibling->GetTailContinuation();
5890 }
5891
5892 if (!IsValidSibling(aSibling, aTargetContent, aTargetContentDisplay)) {
5893 return nullptr;
5894 }
5895
5896 return aSibling;
5897}
5898
5899nsIFrame* nsCSSFrameConstructor::FindPreviousSibling(
5900 const FlattenedChildIterator& aIter,
5901 Maybe<StyleDisplay>& aTargetContentDisplay) {
5902 return FindSibling<SiblingDirection::Backward>(aIter, aTargetContentDisplay);
5903}
5904
5905nsIFrame* nsCSSFrameConstructor::FindNextSibling(
5906 const FlattenedChildIterator& aIter,
5907 Maybe<StyleDisplay>& aTargetContentDisplay) {
5908 return FindSibling<SiblingDirection::Forward>(aIter, aTargetContentDisplay);
5909}
5910
5911template <nsCSSFrameConstructor::SiblingDirection aDirection>
5912nsIFrame* nsCSSFrameConstructor::FindSibling(
5913 const FlattenedChildIterator& aIter,
5914 Maybe<StyleDisplay>& aTargetContentDisplay) {
5915 nsIContent* targetContent = aIter.Get();
5916 FlattenedChildIterator siblingIter = aIter;
5917 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5918 siblingIter, targetContent, aTargetContentDisplay);
5919 if (sibling) {
5920 return sibling;
5921 }
5922
5923 // Our siblings (if any) do not have a frame to guide us. The frame for the
5924 // target content should be inserted whereever a frame for the container would
5925 // be inserted. This is needed when inserting into display: contents nodes.
5926 const nsIContent* current = aIter.Parent();
5927 while (IsDisplayContents(current)) {
5928 const nsIContent* parent = current->GetFlattenedTreeParent();
5929 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"
, 5929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"No display: contents on the root" ")"); do { *((volatile int
*)__null) = 5929; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5930
5931 FlattenedChildIterator iter(parent);
5932 iter.Seek(current);
5933 sibling = FindSiblingInternal<aDirection>(iter, targetContent,
5934 aTargetContentDisplay);
5935 if (sibling) {
5936 return sibling;
5937 }
5938
5939 current = parent;
5940 }
5941
5942 return nullptr;
5943}
5944
5945// For fieldsets, returns the area frame, if the child is not a legend.
5946static nsContainerFrame* GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
5947 nsIContent* aChildContent) {
5948 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"
, 5948); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->IsTableWrapperFrame()"
") (" "Shouldn't be happening!" ")"); do { *((volatile int*)
__null) = 5948; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5949
5950 nsContainerFrame* newParent = nullptr;
5951 if (aParentFrame->IsFieldSetFrame()) {
5952 // If the parent is a fieldSet, use the fieldSet's area frame as the
5953 // parent unless the new content is a legend.
5954 if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
5955 newParent = static_cast<nsFieldSetFrame*>(aParentFrame)->GetInner();
5956 if (newParent) {
5957 newParent = newParent->GetContentInsertionFrame();
5958 }
5959 }
5960 }
5961 return newParent ? newParent : aParentFrame;
5962}
5963
5964nsIFrame* nsCSSFrameConstructor::GetInsertionPrevSibling(
5965 InsertionPoint* aInsertion, nsIContent* aChild, bool* aIsAppend,
5966 bool* aIsRangeInsertSafe, nsIContent* aStartSkipChild,
5967 nsIContent* aEndSkipChild) {
5968 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"
, 5968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertion->mParentFrame"
") (" "Must have parent frame to start with" ")"); do { *((volatile
int*)__null) = 5968; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5969
5970 *aIsAppend = false;
5971
5972 // Find the frame that precedes the insertion point.
5973 FlattenedChildIterator iter(aInsertion->mContainer);
5974 if (!aChild->IsRootOfNativeAnonymousSubtree()) {
5975 // The check for IsRootOfNativeAnonymousSubtree() is because editor is
5976 // severely broken and calls us directly for native anonymous
5977 // nodes that it creates.
5978 if (aStartSkipChild) {
5979 iter.Seek(aStartSkipChild);
5980 } else {
5981 iter.Seek(aChild);
5982 }
5983 } else {
5984 // Prime the iterator for the call to FindPreviousSibling.
5985 iter.GetNextChild();
5986 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"
, 5988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5988; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5987 "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"
, 5988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5988; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5988 "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"
, 5988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5988; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5989 }
5990
5991 // Note that FindPreviousSibling is passed the iterator by value, so that
5992 // the later usage of the iterator starts from the same place.
5993 Maybe<StyleDisplay> childDisplay;
5994 nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay);
5995
5996 // Now, find the geometric parent so that we can handle
5997 // continuations properly. Use the prev sibling if we have it;
5998 // otherwise use the next sibling.
5999 if (prevSibling) {
6000 aInsertion->mParentFrame =
6001 prevSibling->GetParent()->GetContentInsertionFrame();
6002 } else {
6003 // If there is no previous sibling, then find the frame that follows
6004 //
6005 // FIXME(emilio): This is really complex and probably shouldn't be.
6006 if (aEndSkipChild) {
6007 iter.Seek(aEndSkipChild);
6008 iter.GetPreviousChild();
6009 }
6010 if (nsIFrame* nextSibling = FindNextSibling(iter, childDisplay)) {
6011 aInsertion->mParentFrame =
6012 nextSibling->GetParent()->GetContentInsertionFrame();
6013 } else {
6014 // No previous or next sibling, so treat this like an appended frame.
6015 *aIsAppend = true;
6016
6017 // Deal with fieldsets.
6018 aInsertion->mParentFrame =
6019 ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
6020
6021 aInsertion->mParentFrame =
6022 ::ContinuationToAppendTo(aInsertion->mParentFrame);
6023
6024 prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, nullptr);
6025 }
6026 }
6027
6028 *aIsRangeInsertSafe = childDisplay.isNothing();
6029 return prevSibling;
6030}
6031
6032nsContainerFrame* nsCSSFrameConstructor::GetContentInsertionFrameFor(
6033 nsIContent* aContent) {
6034 nsIFrame* frame;
6035 while (!(frame = aContent->GetPrimaryFrame())) {
6036 if (!IsDisplayContents(aContent)) {
6037 return nullptr;
6038 }
6039
6040 aContent = aContent->GetFlattenedTreeParent();
6041 if (!aContent) {
6042 return nullptr;
6043 }
6044 }
6045
6046 // If the content of the frame is not the desired content then this is not
6047 // really a frame for the desired content.
6048 // XXX This check is needed due to bug 135040. Remove it once that's fixed.
6049 if (frame->GetContent() != aContent) {
6050 return nullptr;
6051 }
6052
6053 nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
6054
6055 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"
, 6057); MOZ_PretendNoReturn(); } } while (0)
6056 "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"
, 6057); MOZ_PretendNoReturn(); } } while (0)
6057 "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"
, 6057); MOZ_PretendNoReturn(); } } while (0)
;
6058
6059 return insertionFrame;
6060}
6061
6062static bool IsSpecialFramesetChild(nsIContent* aContent) {
6063 // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
6064 return aContent->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame);
6065}
6066
6067static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode);
6068
6069void nsCSSFrameConstructor::AddTextItemIfNeeded(
6070 nsFrameConstructorState& aState, const ComputedStyle& aParentStyle,
6071 const InsertionPoint& aInsertion, nsIContent* aPossibleTextContent,
6072 FrameConstructionItemList& aItems) {
6073 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"
, 6073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleTextContent"
") (" "Must have node" ")"); do { *((volatile int*)__null) =
6073; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
6074 if (!aPossibleTextContent->IsText() ||
6075 !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6076 aPossibleTextContent->HasFlag(NODE_NEEDS_FRAME)) {
6077 // Not text, or not suppressed due to being all-whitespace (if it were being
6078 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6079 // going to be reframed anyway.
6080 return;
6081 }
6082 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"
, 6083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6083 "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"
, 6083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6084 AddFrameConstructionItems(aState, aPossibleTextContent, false, aParentStyle,
6085 aInsertion, aItems);
6086}
6087
6088void nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aContent) {
6089 if (!aContent->IsText() ||
6090 !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6091 aContent->HasFlag(NODE_NEEDS_FRAME)) {
6092 // Not text, or not suppressed due to being all-whitespace (if it were being
6093 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6094 // going to be reframed anyway.
6095 return;
6096 }
6097 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"
, 6098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6098; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6098 "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"
, 6098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6098; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6099 ContentInserted(aContent, InsertionKind::Async);
6100}
6101
6102#ifdef DEBUG1
6103void nsCSSFrameConstructor::CheckBitsForLazyFrameConstruction(
6104 nsIContent* aParent) {
6105 // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
6106 // we want to assert, but leaf frames that process their own children and may
6107 // ignore anonymous children (eg framesets) make this complicated. So we set
6108 // these two booleans if we encounter these situations and unset them if we
6109 // hit a node with a leaf frame.
6110 //
6111 // It's fine if one of node without primary frame is in a display:none
6112 // subtree.
6113 //
6114 // Also, it's fine if one of the nodes without primary frame is a display:
6115 // contents node.
6116 bool noPrimaryFrame = false;
6117 bool needsFrameBitSet = false;
6118 nsIContent* content = aParent;
6119 while (content && !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
6120 if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
6121 noPrimaryFrame = needsFrameBitSet = false;
6122 }
6123 if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
6124 noPrimaryFrame = !IsDisplayContents(content);
6125 }
6126 if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
6127 needsFrameBitSet = true;
6128 }
6129
6130 content = content->GetFlattenedTreeParent();
6131 }
6132 if (content && content->GetPrimaryFrame() &&
6133 content->GetPrimaryFrame()->IsLeaf()) {
6134 noPrimaryFrame = needsFrameBitSet = false;
6135 }
6136 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"
, 6138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6137 "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"
, 6138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6138 "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"
, 6138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6139 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"
, 6141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6140 "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"
, 6141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6141 "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"
, 6141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6142}
6143#endif
6144
6145// Returns true if this operation can be lazy, false if not.
6146//
6147// FIXME(emilio, bug 1410020): This function assumes that the flattened tree
6148// parent of all the appended children is the same, which, afaict, is not
6149// necessarily true.
6150void nsCSSFrameConstructor::ConstructLazily(Operation aOperation,
6151 nsIContent* aChild) {
6152 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"
, 6152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParent()"
")"); do { *((volatile int*)__null) = 6152; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6153
6154 // We can construct lazily; just need to set suitable bits in the content
6155 // tree.
6156 Element* parent = aChild->GetFlattenedTreeParentElement();
6157 if (!parent) {
6158 // Not part of the flat tree, nothing to do.
6159 return;
6160 }
6161
6162 if (Servo_Element_IsDisplayNone(parent)) {
6163 // Nothing to do either.
6164 //
6165 // FIXME(emilio): This should be an assert, except for weird <frameset>
6166 // stuff that does its own frame construction. Such an assert would fire in
6167 // layout/style/crashtests/1411478.html, for example.
6168 return;
6169 }
6170
6171 // Set NODE_NEEDS_FRAME on the new nodes.
6172 if (aOperation == CONTENTINSERT) {
6173 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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
6174 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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
6175 // 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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
6176 // 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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
6177 // 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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
6178 "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"
, 6178); MOZ_PretendNoReturn(); } } while (0)
;
6179 aChild->SetFlags(NODE_NEEDS_FRAME);
6180 } else { // CONTENTAPPEND
6181 for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
6182 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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
6183 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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
6184 // 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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
6185 // 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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
6186 // 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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
6187 "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"
, 6187); MOZ_PretendNoReturn(); } } while (0)
;
6188 child->SetFlags(NODE_NEEDS_FRAME);
6189 }
6190 }
6191
6192 CheckBitsForLazyFrameConstruction(parent);
6193 parent->NoteDescendantsNeedFramesForServo();
6194}
6195
6196void nsCSSFrameConstructor::IssueSingleInsertNofications(
6197 nsIContent* aStartChild, nsIContent* aEndChild,
6198 InsertionKind aInsertionKind) {
6199 for (nsIContent* child = aStartChild; child != aEndChild;
6200 child = child->GetNextSibling()) {
6201 // XXX the GetContent() != child check is needed due to bug 135040.
6202 // Remove it once that's fixed.
6203 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"
, 6204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6204; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6204 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"
, 6204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6204; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6205
6206 // Call ContentRangeInserted with this node.
6207 ContentRangeInserted(child, child->GetNextSibling(), aInsertionKind);
6208 }
6209}
6210
6211bool nsCSSFrameConstructor::InsertionPoint::IsMultiple() const {
6212 // Fieldset frames have multiple normal flow child frame lists so handle it
6213 // the same as if it had multiple content insertion points.
6214 return mParentFrame && mParentFrame->IsFieldSetFrame();
6215}
6216
6217nsCSSFrameConstructor::InsertionPoint
6218nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aStartChild,
6219 nsIContent* aEndChild,
6220 InsertionKind aInsertionKind) {
6221 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"
, 6221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
")"); do { *((volatile int*)__null) = 6221; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6222
6223 nsIContent* parent = aStartChild->GetParent();
6224 if (!parent) {
6225 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6226 return {};
6227 }
6228
6229 // If the children of the container may be distributed to different insertion
6230 // points, insert them separately and bail out, letting ContentInserted handle
6231 // the mess.
6232 if (parent->GetShadowRoot()) {
6233 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6234 return {};
6235 }
6236
6237#ifdef DEBUG1
6238 {
6239 nsIContent* expectedParent = aStartChild->GetFlattenedTreeParent();
6240 for (nsIContent* child = aStartChild->GetNextSibling(); child;
6241 child = child->GetNextSibling()) {
6242 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"
, 6242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child->GetFlattenedTreeParent() == expectedParent"
")"); do { *((volatile int*)__null) = 6242; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6243 }
6244 }
6245#endif
6246
6247 // Now the flattened tree parent of all the siblings is the same, just use the
6248 // same insertion point and take the fast path, unless it's a multiple
6249 // insertion point.
6250 InsertionPoint ip = GetInsertionPoint(aStartChild);
6251 if (ip.IsMultiple()) {
6252 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6253 return {};
6254 }
6255
6256 return ip;
6257}
6258
6259bool nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
6260 nsIContent* aStartChild,
6261 nsIContent* aEndChild) {
6262 if (aParentFrame->IsFrameSetFrame()) {
6263 // Check whether we have any kids we care about.
6264 for (nsIContent* cur = aStartChild; cur != aEndChild;
6265 cur = cur->GetNextSibling()) {
6266 if (IsSpecialFramesetChild(cur)) {
6267 // Just reframe the parent, since framesets are weird like that.
6268 RecreateFramesForContent(aParentFrame->GetContent(),
6269 InsertionKind::Async);
6270 return true;
6271 }
6272 }
6273 }
6274 return false;
6275}
6276
6277void nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild,
6278 nsIContent* aEndChild) {
6279 for (nsIContent* child = aStartChild; child != aEndChild;
6280 child = child->GetNextSibling()) {
6281 if (child->IsElement()) {
6282 child->AsElement()->NoteDirtyForServo();
6283 }
6284 }
6285}
6286
6287#ifdef DEBUG1
6288static bool IsFlattenedTreeChild(nsIContent* aParent, nsIContent* aChild) {
6289 FlattenedChildIterator iter(aParent);
6290 for (nsIContent* node = iter.GetNextChild(); node;
6291 node = iter.GetNextChild()) {
6292 if (node == aChild) {
6293 return true;
6294 }
6295 }
6296 return false;
6297}
6298#endif
6299
6300void nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
6301 nsIContent* aEndChild) {
6302 ServoStyleSet* styleSet = mPresShell->StyleSet();
6303
6304 for (nsIContent* child = aStartChild; child != aEndChild;
6305 child = child->GetNextSibling()) {
6306 if (!child->IsElement()) {
6307 continue;
6308 }
6309
6310 Element* childElement = child->AsElement();
6311
6312 // We only come in here from non-lazy frame construction, so the children
6313 // should be unstyled.
6314 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"
, 6314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!childElement->HasServoData()"
")"); do { *((volatile int*)__null) = 6314; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6315
6316#ifdef DEBUG1
6317 {
6318 // Furthermore, all of them should have the same flattened tree parent
6319 // (GetRangeInsertionPoint ensures it). And that parent should be styled,
6320 // otherwise we would've never found an insertion point at all.
6321 Element* parent = childElement->GetFlattenedTreeParentElement();
6322 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"
, 6322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ")"
); do { *((volatile int*)__null) = 6322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6323 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"
, 6323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasServoData()"
")"); do { *((volatile int*)__null) = 6323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6324 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"
, 6326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6325 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"
, 6326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6326 "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"
, 6326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6327 }
6328#endif
6329
6330 styleSet->StyleNewSubtree(childElement);
6331 }
6332}
6333
6334nsIFrame* nsCSSFrameConstructor::FindNextSiblingForAppend(
6335 const InsertionPoint& aInsertion) {
6336 auto SlowPath = [&]() -> nsIFrame* {
6337 FlattenedChildIterator iter(aInsertion.mContainer,
6338 /* aStartAtBeginning = */ false);
6339 iter.GetPreviousChild(); // Prime the iterator.
6340 Maybe<StyleDisplay> unused;
6341 return FindNextSibling(iter, unused);
6342 };
6343
6344 if (!IsDisplayContents(aInsertion.mContainer) &&
6345 !nsLayoutUtils::GetAfterFrame(aInsertion.mContainer)) {
6346 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"
, 6346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!SlowPath()"
")"); do { *((volatile int*)__null) = 6346; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6347 return nullptr;
6348 }
6349
6350 return SlowPath();
6351}
6352
6353// This is a bit slow, but sometimes we need it.
6354static bool ParentIsWrapperAnonBox(nsIFrame* aParent) {
6355 nsIFrame* maybeAnonBox = aParent;
6356 if (maybeAnonBox->Style()->GetPseudoType() == PseudoStyleType::cellContent) {
6357 // The thing that would maybe be a wrapper anon box is the cell.
6358 maybeAnonBox = maybeAnonBox->GetParent();
6359 }
6360 return maybeAnonBox->Style()->IsWrapperAnonBox();
6361}
6362
6363void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
6364 InsertionKind aInsertionKind) {
6365 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"
, 6366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6366 !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"
, 6366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6367
6368 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentAppended",mozilla::AutoProfilerLabelHot raiiObject6369( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6369 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6369( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6370 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6371
6372#ifdef DEBUG1
6373 if (gNoisyContentUpdates) {
6374 printf(
6375 "nsCSSFrameConstructor::ContentAppended container=%p "
6376 "first-child=%p lazy=%d\n",
6377 aFirstNewContent->GetParent(), aFirstNewContent,
6378 aInsertionKind == InsertionKind::Async);
6379 if (gReallyNoisyContentUpdates && aFirstNewContent->GetParent()) {
6380 aFirstNewContent->GetParent()->List(stdoutstdout, 0);
6381 }
6382 }
6383
6384 for (nsIContent* child = aFirstNewContent; child;
6385 child = child->GetNextSibling()) {
6386 // XXX the GetContent() != child check is needed due to bug 135040.
6387 // Remove it once that's fixed.
6388 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"
, 6391); 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) = 6391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6389 !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"
, 6391); 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) = 6391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6390 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"
, 6391); 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) = 6391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6391 "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"
, 6391); 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) = 6391; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6392 }
6393#endif
6394
6395 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6396 InsertionPoint insertion =
6397 GetRangeInsertionPoint(aFirstNewContent, nullptr, aInsertionKind);
6398 nsContainerFrame*& parentFrame = insertion.mParentFrame;
6399 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6400 if (!parentFrame) {
6401 // We're punting on frame construction because there's no container frame.
6402 // The Servo-backed style system handles this case like the lazy frame
6403 // construction case, except when we're already constructing frames, in
6404 // which case we shouldn't need to do anything else.
6405 if (aInsertionKind == InsertionKind::Async) {
6406 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6407 }
6408 return;
6409 }
6410
6411 if (aInsertionKind == InsertionKind::Async) {
6412 ConstructLazily(CONTENTAPPEND, aFirstNewContent);
6413 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6414 return;
6415 }
6416
6417 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6418 if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
6419 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6420 return;
6421 }
6422 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6423
6424 if (parentFrame->IsLeaf()) {
6425 // Nothing to do here; we shouldn't be constructing kids of leaves
6426 // Clear lazy bits so we don't try to construct again.
6427 ClearLazyBits(aFirstNewContent, nullptr);
6428 return;
6429 }
6430
6431 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6432 if (WipeInsertionParent(parentFrame)) {
6433 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6434 return;
6435 }
6436 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6437
6438#ifdef DEBUG1
6439 if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
6440 printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
6441 parentFrame->ListTag(stdoutstdout);
6442 printf(" is ib-split\n");
6443 }
6444#endif
6445
6446 // We should never get here with fieldsets, since they have
6447 // multiple insertion points.
6448 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"
, 6449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6449; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6449 "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"
, 6449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6449; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6450
6451 nsIFrame* nextSibling = FindNextSiblingForAppend(insertion);
6452 if (nextSibling) {
6453 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6454 } else {
6455 parentFrame = ::ContinuationToAppendTo(parentFrame);
6456 }
6457
6458 nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
6459
6460 // See if the containing block has :first-letter style applied.
6461 const bool haveFirstLetterStyle =
6462 containingBlock && HasFirstLetterStyle(containingBlock);
6463
6464 const bool haveFirstLineStyle =
6465 containingBlock && ShouldHaveFirstLineStyle(containingBlock->GetContent(),
6466 containingBlock->Style());
6467
6468 if (haveFirstLetterStyle) {
6469 AutoWeakFrame wf(nextSibling);
6470
6471 // Before we get going, remove the current letter frames
6472 RemoveLetterFrames(mPresShell, containingBlock);
6473
6474 // Reget nextSibling, since we may have killed it.
6475 //
6476 // FIXME(emilio): This kinda sucks! :(
6477 if (nextSibling && !wf) {
6478 nextSibling = FindNextSiblingForAppend(insertion);
6479 if (nextSibling) {
6480 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6481 containingBlock = GetFloatContainingBlock(parentFrame);
6482 }
6483 }
6484 }
6485
6486 // Create some new frames
6487 nsFrameConstructorState state(
6488 mPresShell, GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
6489 GetAbsoluteContainingBlock(parentFrame, ABS_POS), containingBlock);
6490
6491 if (mPresShell->GetPresContext()->IsPaginated()) {
6492 // Because this function can be called outside frame construction, we need
6493 // to set state.mAutoPageNameValue based on what the parent frame's auto
6494 // value is.
6495 // Calling this from outside the frame constructor can violate many of the
6496 // expectations in AutoFrameConstructionPageName, and unlike during frame
6497 // construction we already have an auto value from parentFrame, so we do
6498 // not use AutoFrameConstructionPageName here.
6499 state.mAutoPageNameValue = parentFrame->GetAutoPageValue();
6500#ifdef DEBUG1
6501 parentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
6502#endif
6503 }
6504
6505 LayoutFrameType frameType = parentFrame->Type();
6506
6507 RefPtr<ComputedStyle> parentStyle =
6508 ResolveComputedStyle(insertion.mContainer);
6509 FlattenedChildIterator iter(insertion.mContainer);
6510 const bool haveNoShadowDOM =
6511 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6512
6513 AutoFrameConstructionItemList items(this);
6514 if (aFirstNewContent->GetPreviousSibling() &&
6515 GetParentType(frameType) == eTypeBlock && haveNoShadowDOM) {
6516 // If there's a text node in the normal content list just before the new
6517 // items, and it has no frame, make a frame construction item for it. If it
6518 // doesn't need a frame, ConstructFramesFromItemList below won't give it
6519 // one. No need to do all this if our parent type is not block, though,
6520 // since WipeContainingBlock already handles that situation.
6521 //
6522 // Because we're appending, we don't need to worry about any text
6523 // after the appended content; there can only be generated content
6524 // (and bare text nodes are not generated). Native anonymous content
6525 // generated by frames never participates in inline layout.
6526 AddTextItemIfNeeded(state, *parentStyle, insertion,
6527 aFirstNewContent->GetPreviousSibling(), items);
6528 }
6529 for (nsIContent* child = aFirstNewContent; child;
6530 child = child->GetNextSibling()) {
6531 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
6532 items);
6533 }
6534
6535 nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling);
6536
6537 // Perform special check for diddling around with the frames in
6538 // a ib-split inline frame.
6539 // If we're appending before :after content, then we're not really
6540 // appending, so let WipeContainingBlock know that.
6541 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6542 if (WipeContainingBlock(state, containingBlock, parentFrame, items, true,
6543 prevSibling)) {
6544 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6545 return;
6546 }
6547 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6548
6549 // If the parent is a block frame, and we're not in a special case
6550 // where frames can be moved around, determine if the list is for the
6551 // start or end of the block.
6552 if (parentFrame->IsBlockFrameOrSubclass() && !haveFirstLetterStyle &&
6553 !haveFirstLineStyle && !IsFramePartOfIBSplit(parentFrame)) {
6554 items.SetLineBoundaryAtStart(!prevSibling ||
6555 !prevSibling->IsInlineOutside() ||
6556 prevSibling->IsBrFrame());
6557 // :after content can't be <br> so no need to check it
6558 //
6559 // FIXME(emilio): A display: contents sibling could! Write a test-case and
6560 // fix.
6561 items.SetLineBoundaryAtEnd(!nextSibling || !nextSibling->IsInlineOutside());
6562 }
6563 // To suppress whitespace-only text frames, we have to verify that
6564 // our container's DOM child list matches its flattened tree child list.
6565 items.SetParentHasNoShadowDOM(haveNoShadowDOM);
6566
6567 nsFrameConstructorSaveState floatSaveState;
6568 state.MaybePushFloatContainingBlock(parentFrame, floatSaveState);
6569
6570 nsFrameList frameList;
6571 ConstructFramesFromItemList(state, items, parentFrame,
6572 ParentIsWrapperAnonBox(parentFrame), frameList);
6573
6574 for (nsIContent* child = aFirstNewContent; child;
6575 child = child->GetNextSibling()) {
6576 // Invalidate now instead of before the WipeContainingBlock call, just in
6577 // case we do wipe; in that case we don't need to do this walk at all.
6578 // XXXbz does that matter? Would it make more sense to save some virtual
6579 // GetChildAt_Deprecated calls instead and do this during construction of
6580 // our FrameConstructionItemList?
6581 InvalidateCanvasIfNeeded(mPresShell, child);
6582 }
6583
6584 // If the container is a table and a caption was appended, it needs to be put
6585 // in the table wrapper frame's additional child list.
6586 nsFrameList captionList;
6587 if (LayoutFrameType::Table == frameType) {
6588 // Pull out the captions. Note that we don't want to do that as we go,
6589 // because processing a single caption can add a whole bunch of things to
6590 // the frame items due to pseudoframe processing. So we'd have to pull
6591 // captions from a list anyway; might as well do that here.
6592 // XXXbz this is no longer true; we could pull captions directly out of the
6593 // FrameConstructionItemList now.
6594 PullOutCaptionFrames(frameList, captionList);
6595 }
6596
6597 if (haveFirstLineStyle && parentFrame == containingBlock) {
6598 // It's possible that some of the new frames go into a
6599 // first-line frame. Look at them and see...
6600 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
6601 frameList);
6602 // That moved things into line frames as needed, reparenting their
6603 // styles. Nothing else needs to be done.
6604 } else if (parentFrame->Style()->HasPseudoElementData()) {
6605 // parentFrame might be inside a ::first-line frame. Check whether it is,
6606 // and if so fix up our styles.
6607 CheckForFirstLineInsertion(parentFrame, frameList);
6608 CheckForFirstLineInsertion(parentFrame, captionList);
6609 }
6610
6611 // Notify the parent frame passing it the list of new frames
6612 // Append the flowed frames to the principal child list; captions
6613 // need special treatment
6614 if (captionList.NotEmpty()) { // append the caption to the table wrapper
6615 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"
, 6615); MOZ_PretendNoReturn(); } } while (0)
;
6616 nsContainerFrame* outerTable = parentFrame->GetParent();
6617 captionList.ApplySetParent(outerTable);
6618 AppendFrames(outerTable, FrameChildListID::Caption, std::move(captionList));
6619 }
6620
6621 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6622 if (MaybeRecreateForColumnSpan(state, parentFrame, frameList, prevSibling)) {
6623 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6624 return;
6625 }
6626 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6627
6628 if (frameList.NotEmpty()) { // append the in-flow kids
6629 AppendFramesToParent(state, parentFrame, frameList, prevSibling);
6630 }
6631
6632 // Recover first-letter frames
6633 if (haveFirstLetterStyle) {
6634 RecoverLetterFrames(containingBlock);
6635 }
6636
6637#ifdef DEBUG1
6638 if (gReallyNoisyContentUpdates) {
6639 printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
6640 parentFrame->List(stdoutstdout);
6641 }
6642#endif
6643
6644#ifdef ACCESSIBILITY1
6645 if (nsAccessibilityService* accService = GetAccService()) {
6646 accService->ContentRangeInserted(mPresShell, aFirstNewContent, nullptr);
6647 }
6648#endif
6649}
6650
6651void nsCSSFrameConstructor::ContentInserted(nsIContent* aChild,
6652 InsertionKind aInsertionKind) {
6653 ContentRangeInserted(aChild, aChild->GetNextSibling(), aInsertionKind);
6654}
6655
6656// ContentRangeInserted handles creating frames for a range of nodes that
6657// aren't at the end of their childlist. ContentRangeInserted isn't a real
6658// content notification, but rather it handles regular ContentInserted calls
6659// for a single node as well as the lazy construction of frames for a range of
6660// nodes when called from CreateNeededFrames. For a range of nodes to be
6661// suitable to have its frames constructed all at once they must meet the same
6662// conditions that ContentAppended imposes (GetRangeInsertionPoint checks
6663// these), plus more. Namely when finding the insertion prevsibling we must not
6664// need to consult something specific to any one node in the range, so that the
6665// insertion prevsibling would be the same for each node in the range. So we
6666// pass the first node in the range to GetInsertionPrevSibling, and if
6667// IsValidSibling (the only place GetInsertionPrevSibling might look at the
6668// passed in node itself) needs to resolve style on the node we record this and
6669// return that this range needs to be split up and inserted separately. Table
6670// captions need extra attention as we need to determine where to insert them
6671// in the caption list, while skipping any nodes in the range being inserted
6672// (because when we treat the caption frames the other nodes have had their
6673// frames constructed but not yet inserted into the frame tree).
6674void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
6675 nsIContent* aEndChild,
6676 InsertionKind aInsertionKind) {
6677 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"
, 6678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6678; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6678 !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"
, 6678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6678; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6679
6680 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentRangeInserted",mozilla::AutoProfilerLabelHot raiiObject6681( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6681 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6681( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6682 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6683
6684 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"
, 6684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
") (" "must always pass a child" ")"); do { *((volatile int*
)__null) = 6684; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6685
6686#ifdef DEBUG1
6687 if (gNoisyContentUpdates) {
6688 printf(
6689 "nsCSSFrameConstructor::ContentRangeInserted container=%p "
6690 "start-child=%p end-child=%p lazy=%d\n",
6691 aStartChild->GetParent(), aStartChild, aEndChild,
6692 aInsertionKind == InsertionKind::Async);
6693 if (gReallyNoisyContentUpdates) {
6694 if (aStartChild->GetParent()) {
6695 aStartChild->GetParent()->List(stdoutstdout, 0);
6696 } else {
6697 aStartChild->List(stdoutstdout, 0);
6698 }
6699 }
6700 }
6701
6702 for (nsIContent* child = aStartChild; child != aEndChild;
6703 child = child->GetNextSibling()) {
6704 // XXX the GetContent() != child check is needed due to bug 135040.
6705 // Remove it once that's fixed.
6706 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"
, 6709); MOZ_PretendNoReturn(); } } while (0)
6707 !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"
, 6709); MOZ_PretendNoReturn(); } } while (0)
6708 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"
, 6709); MOZ_PretendNoReturn(); } } while (0)
6709 "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"
, 6709); MOZ_PretendNoReturn(); } } while (0)
;
6710 }
6711#endif
6712
6713 bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
6714 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"
, 6715); MOZ_PretendNoReturn(); } } while (0)
6715 "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"
, 6715); MOZ_PretendNoReturn(); } } while (0)
;
6716 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"
, 6717); MOZ_PretendNoReturn(); } } while (0)
6717 "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"
, 6717); MOZ_PretendNoReturn(); } } while (0)
;
6718
6719 // If we have a null parent, then this must be the document element being
6720 // inserted, or some other child of the document in the DOM (might be a PI,
6721 // say).
6722 if (!aStartChild->GetParent()) {
6723 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"
, 6724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6724 "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"
, 6724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6725 Element* docElement = mDocument->GetRootElement();
6726 if (aStartChild != docElement) {
6727 // Not the root element; just bail out
6728 return;
6729 }
6730
6731 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"
, 6731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "root element frame already created" ")"); do { *((volatile
int*)__null) = 6731; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6732 if (aInsertionKind == InsertionKind::Async) {
6733 docElement->SetFlags(NODE_NEEDS_FRAME);
6734 LazilyStyleNewChildRange(docElement, nullptr);
6735 return;
6736 }
6737
6738 // Create frames for the document element and its child elements
6739 if (ConstructDocElementFrame(docElement)) {
6740 InvalidateCanvasIfNeeded(mPresShell, aStartChild);
6741#ifdef DEBUG1
6742 if (gReallyNoisyContentUpdates) {
6743 printf(
6744 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
6745 "model:\n");
6746 mRootElementFrame->List(stdoutstdout);
6747 }
6748#endif
6749 }
6750
6751#ifdef ACCESSIBILITY1
6752 if (nsAccessibilityService* accService = GetAccService()) {
6753 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
6754 }
6755#endif
6756
6757 return;
6758 }
6759
6760 InsertionPoint insertion;
6761 if (isSingleInsert) {
6762 // See if we have a Shadow DOM insertion point. If so, then that's our real
6763 // parent frame; if not, then the frame hasn't been built yet and we just
6764 // bail.
6765 insertion = GetInsertionPoint(aStartChild);
6766 } else {
6767 // Get our insertion point. If we need to issue single ContentInserteds
6768 // GetRangeInsertionPoint will take care of that for us.
6769 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6770 insertion = GetRangeInsertionPoint(aStartChild, aEndChild, aInsertionKind);
6771 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6772 }
6773
6774 if (!insertion.mParentFrame) {
6775 // We're punting on frame construction because there's no container frame.
6776 // The Servo-backed style system handles this case like the lazy frame
6777 // construction case, except when we're already constructing frames, in
6778 // which case we shouldn't need to do anything else.
6779 if (aInsertionKind == InsertionKind::Async) {
6780 LazilyStyleNewChildRange(aStartChild, aEndChild);
6781 }
6782 return;
6783 }
6784
6785 if (aInsertionKind == InsertionKind::Async) {
6786 ConstructLazily(CONTENTINSERT, aStartChild);
6787 LazilyStyleNewChildRange(aStartChild, aEndChild);
6788 return;
6789 }
6790
6791 bool isAppend, isRangeInsertSafe;
6792 nsIFrame* prevSibling = GetInsertionPrevSibling(
6793 &insertion, aStartChild, &isAppend, &isRangeInsertSafe);
6794
6795 // check if range insert is safe
6796 if (!isSingleInsert && !isRangeInsertSafe) {
6797 // must fall back to a single ContertInserted for each child in the range
6798 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6799 IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
6800 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6801 return;
6802 }
6803
6804 LayoutFrameType frameType = insertion.mParentFrame->Type();
6805 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6806 if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild,
6807 aEndChild)) {
6808 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6809 return;
6810 }
6811 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6812
6813 // We should only get here with fieldsets when doing a single insert, because
6814 // fieldsets have multiple insertion points.
6815 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"
, 6816); MOZ_PretendNoReturn(); } } while (0)
6816 "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"
, 6816); MOZ_PretendNoReturn(); } } while (0)
;
6817 // Note that this check is insufficient if aStartChild is not a legend with
6818 // display::contents that contains a legend. We'll catch that case in
6819 // WipeContainingBlock. (That code would also catch this case, but handling
6820 // this early is slightly faster.)
6821 // XXXmats we should be able to optimize this when the fieldset doesn't
6822 // currently have a rendered legend. ContentRangeInserted needs to be fixed
6823 // to use the inner frame as the content insertion frame in that case.
6824 if (GetFieldSetFrameFor(insertion.mParentFrame) &&
6825 aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
6826 // Just reframe the parent, since figuring out whether this
6827 // should be the new legend and then handling it is too complex.
6828 // We could do a little better here --- check if the fieldset already
6829 // has a legend which occurs earlier in its child list than this node,
6830 // and if so, proceed. But we'd have to extend nsFieldSetFrame
6831 // to locate this legend in the inserted frames and extract it.
6832 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6833 RecreateFramesForContent(insertion.mParentFrame->GetContent(),
6834 InsertionKind::Async);
6835 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6836 return;
6837 }
6838
6839 // Don't construct kids of leaves
6840 if (insertion.mParentFrame->IsLeaf()) {
6841 // Clear lazy bits so we don't try to construct again.
6842 ClearLazyBits(aStartChild, aEndChild);
6843 return;
6844 }
6845
6846 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6847 if (WipeInsertionParent(insertion.mParentFrame)) {
6848 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6849 return;
6850 }
6851 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6852
6853 nsFrameConstructorState state(
6854 mPresShell, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
6855 GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
6856 GetFloatContainingBlock(insertion.mParentFrame),
6857 do_AddRef(mFrameTreeState));
6858
6859 // Recover state for the containing block - we need to know if
6860 // it has :first-letter or :first-line style applied to it. The
6861 // reason we care is that the internal structure in these cases
6862 // is not the normal structure and requires custom updating
6863 // logic.
6864 nsContainerFrame* containingBlock = state.mFloatedList.mContainingBlock;
6865 bool haveFirstLetterStyle = false;
6866 bool haveFirstLineStyle = false;
6867
6868 // In order to shave off some cycles, we only dig up the
6869 // containing block haveFirst* flags if the parent frame where
6870 // the insertion/append is occurring is an inline or block
6871 // container. For other types of containers this isn't relevant.
6872 StyleDisplayInside parentDisplayInside =
6873 insertion.mParentFrame->StyleDisplay()->DisplayInside();
6874
6875 // Examine the insertion.mParentFrame where the insertion is taking
6876 // place. If it's a certain kind of container then some special
6877 // processing is done.
6878 if (StyleDisplayInside::Flow == parentDisplayInside) {
6879 // Recover the special style flags for the containing block
6880 if (containingBlock) {
6881 haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
6882 haveFirstLineStyle = ShouldHaveFirstLineStyle(
6883 containingBlock->GetContent(), containingBlock->Style());
6884 }
6885
6886 if (haveFirstLetterStyle) {
6887 // If our current insertion.mParentFrame is a Letter frame, use its parent
6888 // as our new parent hint
6889 if (insertion.mParentFrame->IsLetterFrame()) {
6890 // If insertion.mParentFrame is out of flow, then we actually want the
6891 // parent of the placeholder frame.
6892 if (insertion.mParentFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
6893 nsPlaceholderFrame* placeholderFrame =
6894 insertion.mParentFrame->GetPlaceholderFrame();
6895 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"
, 6895); MOZ_PretendNoReturn(); } } while (0)
;
6896 insertion.mParentFrame = placeholderFrame->GetParent();
6897 } else {
6898 insertion.mParentFrame = insertion.mParentFrame->GetParent();
6899 }
6900 }
6901
6902 // Remove the old letter frames before doing the insertion
6903 RemoveLetterFrames(mPresShell, state.mFloatedList.mContainingBlock);
6904
6905 // Removing the letterframes messes around with the frame tree, removing
6906 // and creating frames. We need to reget our prevsibling, parent frame,
6907 // etc.
6908 prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend,
6909 &isRangeInsertSafe);
6910
6911 // Need check whether a range insert is still safe.
6912 if (!isSingleInsert && !isRangeInsertSafe) {
6913 // Need to recover the letter frames first.
6914 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
6915
6916 // must fall back to a single ContertInserted for each child in the
6917 // range
6918 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6919 IssueSingleInsertNofications(aStartChild, aEndChild,
6920 InsertionKind::Sync);
6921 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6922 return;
6923 }
6924
6925 frameType = insertion.mParentFrame->Type();
6926 }
6927 }
6928
6929 // This handles fallback to 'list-style-type' when a 'list-style-image' fails
6930 // to load.
6931 if (aStartChild->IsInNativeAnonymousSubtree() &&
6932 aStartChild->IsHTMLElement(nsGkAtoms::mozgeneratedcontentimage)) {
6933 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"
, 6933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
")"); do { *((volatile int*)__null) = 6933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6934 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"
, 6936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6936; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6935 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"
, 6936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6936; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6936 "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"
, 6936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6936; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6937 nsIContent* const nextSibling = aStartChild->GetNextSibling();
6938 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"
, 6939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6939; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6939 "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"
, 6939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6939; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6940 DestroyContext context(mPresShell);
6941 RemoveFrame(context, FrameChildListID::Principal,
6942 nextSibling->GetPrimaryFrame());
6943 auto* const container = aStartChild->GetParent()->AsElement();
6944 nsIContent* firstNewChild = nullptr;
6945 auto InsertChild = [this, container, nextSibling,
6946 &firstNewChild](RefPtr<nsIContent>&& aChild) {
6947 // We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
6948 // here; it would get set under AppendChildTo. But AppendChildTo might
6949 // think that we're going from not being anonymous to being anonymous and
6950 // do some extra work; setting the flag here avoids that.
6951 aChild->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
6952 container->InsertChildBefore(aChild, nextSibling, false, IgnoreErrors());
6953 if (auto* childElement = Element::FromNode(aChild)) {
6954 // If we created any children elements, Servo needs to traverse them,
6955 // but the root is already set up.
6956 mPresShell->StyleSet()->StyleNewSubtree(childElement);
6957 }
6958 if (!firstNewChild) {
6959 firstNewChild = aChild;
6960 }
6961 };
6962 CreateGeneratedContentFromListStyleType(
6963 state, *insertion.mContainer->AsElement(),
6964 *insertion.mParentFrame->Style(), InsertChild);
6965 if (!firstNewChild) {
6966 // No fallback content - we're done.
6967 return;
6968 }
6969 aStartChild = firstNewChild;
6970 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"
, 6971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6971; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6971 "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"
, 6971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6971; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6972 }
6973
6974 AutoFrameConstructionItemList items(this);
6975 RefPtr<ComputedStyle> parentStyle =
6976 ResolveComputedStyle(insertion.mContainer);
6977 ParentType parentType = GetParentType(frameType);
6978 FlattenedChildIterator iter(insertion.mContainer);
6979 const bool haveNoShadowDOM =
6980 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6981 if (aStartChild->GetPreviousSibling() && parentType == eTypeBlock &&
6982 haveNoShadowDOM) {
6983 // If there's a text node in the normal content list just before the
6984 // new nodes, and it has no frame, make a frame construction item for
6985 // it, because it might need a frame now. No need to do this if our
6986 // parent type is not block, though, since WipeContainingBlock
6987 // already handles that situation.
6988 AddTextItemIfNeeded(state, *parentStyle, insertion,
6989 aStartChild->GetPreviousSibling(), items);
6990 }
6991
6992 if (isSingleInsert) {
6993 AddFrameConstructionItems(state, aStartChild,
6994 aStartChild->IsRootOfNativeAnonymousSubtree(),
6995 *parentStyle, insertion, items);
6996 } else {
6997 for (nsIContent* child = aStartChild; child != aEndChild;
6998 child = child->GetNextSibling()) {
6999 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
7000 items);
7001 }
7002 }
7003
7004 if (aEndChild && parentType == eTypeBlock && haveNoShadowDOM) {
7005 // If there's a text node in the normal content list just after the
7006 // new nodes, and it has no frame, make a frame construction item for
7007 // it, because it might need a frame now. No need to do this if our
7008 // parent type is not block, though, since WipeContainingBlock
7009 // already handles that situation.
7010 AddTextItemIfNeeded(state, *parentStyle, insertion, aEndChild, items);
7011 }
7012
7013 // Perform special check for diddling around with the frames in
7014 // a special inline frame.
7015 // If we're appending before :after content, then we're not really
7016 // appending, so let WipeContainingBlock know that.
7017 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7018 if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items,
7019 isAppend, prevSibling)) {
7020 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7021 return;
7022 }
7023 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7024
7025 nsFrameConstructorSaveState floatSaveState;
7026 state.MaybePushFloatContainingBlock(insertion.mParentFrame, floatSaveState);
7027
7028 if (state.mPresContext->IsPaginated()) {
7029 // Because this function can be called outside frame construction, we need
7030 // to set state.mAutoPageNameValue based on what the parent frame's auto
7031 // value is.
7032 // Calling this from outside the frame constructor can violate many of the
7033 // expectations in AutoFrameConstructionPageName, and unlike during frame
7034 // construction we already have an auto value from parentFrame, so we do
7035 // not use AutoFrameConstructionPageName here.
7036 state.mAutoPageNameValue = insertion.mParentFrame->GetAutoPageValue();
7037#ifdef DEBUG1
7038 insertion.mParentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
7039#endif
7040 }
7041
7042 // If the container is a table and a caption will be appended, it needs to be
7043 // put in the table wrapper frame's additional child list.
7044 // We make no attempt here to set flags to indicate whether the list
7045 // will be at the start or end of a block. It doesn't seem worthwhile.
7046 nsFrameList frameList, captionList;
7047 ConstructFramesFromItemList(state, items, insertion.mParentFrame,
7048 ParentIsWrapperAnonBox(insertion.mParentFrame),
7049 frameList);
7050
7051 if (frameList.NotEmpty()) {
7052 for (nsIContent* child = aStartChild; child != aEndChild;
7053 child = child->GetNextSibling()) {
7054 InvalidateCanvasIfNeeded(mPresShell, child);
7055 }
7056
7057 if (LayoutFrameType::Table == frameType ||
7058 LayoutFrameType::TableWrapper == frameType) {
7059 PullOutCaptionFrames(frameList, captionList);
7060 if (prevSibling && prevSibling->IsTableCaption()) {
7061 // This can happen, but only if the table is empty (otherwise
7062 // SafeToInsertPseudoNeedingChildren bails).
7063 prevSibling = nullptr;
7064 }
7065 }
7066 }
7067
7068 if (haveFirstLineStyle && insertion.mParentFrame == containingBlock &&
7069 isAppend) {
7070 // It's possible that the new frame goes into a first-line
7071 // frame. Look at it and see...
7072 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
7073 frameList);
7074 } else if (insertion.mParentFrame->Style()->HasPseudoElementData()) {
7075 CheckForFirstLineInsertion(insertion.mParentFrame, frameList);
7076 CheckForFirstLineInsertion(insertion.mParentFrame, captionList);
7077 }
7078
7079 // We might have captions; put them into the caption list of the
7080 // table wrapper frame.
7081 if (captionList.NotEmpty()) {
7082 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"
, 7084); MOZ_PretendNoReturn(); } } while (0)
7083 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"
, 7084); MOZ_PretendNoReturn(); } } while (0)
7084 "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"
, 7084); MOZ_PretendNoReturn(); } } while (0)
;
7085 // We need to determine where to put the caption items; start with the
7086 // the parent frame that has already been determined and get the insertion
7087 // prevsibling of the first caption item.
7088 bool captionIsAppend;
7089 nsIFrame* captionPrevSibling = nullptr;
7090
7091 // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
7092 bool ignored;
7093 InsertionPoint captionInsertion = insertion;
7094 if (isSingleInsert) {
7095 captionPrevSibling = GetInsertionPrevSibling(
7096 &captionInsertion, aStartChild, &captionIsAppend, &ignored);
7097 } else {
7098 nsIContent* firstCaption = captionList.FirstChild()->GetContent();
7099 // It is very important here that we skip the children in
7100 // [aStartChild,aEndChild) when looking for a
7101 // prevsibling.
7102 captionPrevSibling = GetInsertionPrevSibling(
7103 &captionInsertion, firstCaption, &captionIsAppend, &ignored,
7104 aStartChild, aEndChild);
7105 }
7106
7107 nsContainerFrame* outerTable =
7108 captionInsertion.mParentFrame->IsTableFrame()
7109 ? captionInsertion.mParentFrame->GetParent()
7110 : captionInsertion.mParentFrame;
7111
7112 // If the parent is not a table wrapper frame we will try to add frames
7113 // to a named child list that the parent does not honor and the frames
7114 // will get lost.
7115 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"
, 7117); 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) = 7117; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7116 "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"
, 7117); 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) = 7117; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7117 "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"
, 7117); 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) = 7117; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7118
7119 // If the parent of our current prevSibling is different from the frame
7120 // we'll actually use as the parent, then the calculated insertion
7121 // point is now invalid (bug 341382).
7122 if (captionPrevSibling && captionPrevSibling->GetParent() != outerTable) {
7123 captionPrevSibling = nullptr;
7124 }
7125
7126 captionList.ApplySetParent(outerTable);
7127 if (captionIsAppend) {
7128 AppendFrames(outerTable, FrameChildListID::Caption,
7129 std::move(captionList));
7130 } else {
7131 InsertFrames(outerTable, FrameChildListID::Caption, captionPrevSibling,
7132 std::move(captionList));
7133 }
7134 }
7135
7136 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7137 if (MaybeRecreateForColumnSpan(state, insertion.mParentFrame, frameList,
7138 prevSibling)) {
7139 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7140 return;
7141 }
7142 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7143
7144 if (frameList.NotEmpty()) {
7145 // Notify the parent frame
7146 if (isAppend) {
7147 AppendFramesToParent(state, insertion.mParentFrame, frameList,
7148 prevSibling);
7149 } else {
7150 InsertFrames(insertion.mParentFrame, FrameChildListID::Principal,
7151 prevSibling, std::move(frameList));
7152 }
7153 }
7154
7155 if (haveFirstLetterStyle) {
7156 // Recover the letter frames for the containing block when
7157 // it has first-letter style.
7158 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
7159 }
7160
7161#ifdef DEBUG1
7162 if (gReallyNoisyContentUpdates && insertion.mParentFrame) {
7163 printf(
7164 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
7165 "model:\n");
7166 insertion.mParentFrame->List(stdoutstdout);
7167 }
7168#endif
7169
7170#ifdef ACCESSIBILITY1
7171 if (nsAccessibilityService* accService = GetAccService()) {
7172 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
7173 }
7174#endif
7175}
7176
7177static bool IsWhitespaceFrame(const nsIFrame* aFrame) {
7178 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"
, 7178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 7178
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7179 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
7180}
7181
7182static bool IsSyntheticColGroup(const nsIFrame* aFrame) {
7183 return aFrame->IsTableColGroupFrame() &&
7184 static_cast<const nsTableColGroupFrame*>(aFrame)->IsSynthetic();
7185}
7186
7187static bool IsOnlyNonWhitespaceFrameInList(const nsFrameList& aFrameList,
7188 const nsIFrame* aFrame) {
7189 for (const nsIFrame* f : aFrameList) {
7190 if (f == aFrame) {
7191 // If we have continuations, ignore them too.
7192 aFrame = aFrame->GetNextContinuation();
7193 } else if (!IsWhitespaceFrame(f) && !IsSyntheticColGroup(f)) {
7194 // Synthetic colgroups get created unconditionally, so let's not consider
7195 // them as giving us a non-whitespace frame.
7196 return false;
7197 }
7198 }
7199 return true;
7200}
7201
7202static bool AllChildListsAreEffectivelyEmpty(nsIFrame* aFrame) {
7203 for (auto& [list, listID] : aFrame->ChildLists()) {
7204 if (list.IsEmpty()) {
7205 continue;
7206 }
7207 // We have some existing frame, usually that would be considered as making
7208 // this list nonempty. But let's make an exception for the synthetic
7209 // colgroup that tables have, since that gets created unconditionally.
7210 if (listID == FrameChildListID::ColGroup) {
7211 if (nsIFrame* f = list.OnlyChild(); f && IsSyntheticColGroup(f)) {
7212 continue;
7213 }
7214 }
7215 return false;
7216 }
7217 return true;
7218}
7219
7220static bool SafeToInsertPseudoNeedingChildren(nsIFrame* aFrame) {
7221 return AllChildListsAreEffectivelyEmpty(aFrame);
7222}
7223
7224// Returns true if aFrame is the only meaningful child of aParent (which is
7225// known to be a wrapper-pseudo). This lets us determine whether aParent can be
7226// removed, as a result of aFrame being removed.
7227static bool IsOnlyMeaningfulChildOfWrapperPseudo(nsIFrame* aFrame,
7228 nsIFrame* aParent) {
7229 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"
, 7229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsWrapperPseudo(aParent)"
")"); do { *((volatile int*)__null) = 7229; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7230 // Handle a few special cases with tables and colgroups / captions.
7231 if (aParent->IsTableFrame()) {
7232 auto* wrapper = aParent->GetParent();
7233 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"
, 7233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper" ")"
); do { *((volatile int*)__null) = 7233; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7234 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"
, 7234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7235 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"
, 7236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7236; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7236 "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"
, 7236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7236; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7237 // We can't remove the table if there are any captions present (captions are
7238 // never anonymous themselves), because table wrapper always relies on
7239 // having a table frame.
7240 if (!wrapper->GetChildList(FrameChildListID::Caption).IsEmpty()) {
7241 return false;
7242 }
7243 // Similarly we can't remove the table if there's still a non-anonymous col
7244 // group (unless aFrame _is_ the non-anonymous colgroup).
7245 if (aFrame->IsTableColGroupFrame()) {
7246 return aParent->PrincipalChildList().IsEmpty() &&
7247 IsOnlyNonWhitespaceFrameInList(
7248 aParent->GetChildList(FrameChildListID::ColGroup), aFrame);
7249 }
7250 const auto& colGroupList =
7251 aParent->GetChildList(FrameChildListID::ColGroup);
7252 if (!colGroupList.IsEmpty()) {
7253 nsIFrame* f = colGroupList.OnlyChild();
7254 if (!f || !IsSyntheticColGroup(f)) {
7255 return false;
7256 }
7257 }
7258 }
7259 if (aFrame->IsTableCaption()) {
7260 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"
, 7260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7260; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7261 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"
, 7261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()"
")"); do { *((volatile int*)__null) = 7261; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7262 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"
, 7262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()->IsTableFrame()"
")"); do { *((volatile int*)__null) = 7262; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7263 return IsOnlyNonWhitespaceFrameInList(
7264 aParent->GetChildList(FrameChildListID::Caption), aFrame) &&
7265 // This checks for both colgroups and the principal list of the table
7266 // frame.
7267 AllChildListsAreEffectivelyEmpty(
7268 aParent->PrincipalChildList().OnlyChild());
7269 }
7270 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"
, 7270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableColGroupFrame()"
")"); do { *((volatile int*)__null) = 7270; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7271 return IsOnlyNonWhitespaceFrameInList(aParent->PrincipalChildList(), aFrame);
7272}
7273
7274static bool CanRemoveWrapperPseudoForChildRemoval(nsIFrame* aFrame,
7275 nsIFrame* aParent) {
7276 if (!IsOnlyMeaningfulChildOfWrapperPseudo(aFrame, aParent)) {
7277 return false;
7278 }
7279 if (aParent->IsRubyBaseContainerFrame()) {
7280 // We can't remove the first ruby base container of a ruby frame unless
7281 // it has no siblings. See CreateNeededPseudoSiblings.
7282 return aParent->GetPrevSibling() || !aParent->GetNextSibling();
7283 }
7284 return true;
7285}
7286
7287bool nsCSSFrameConstructor::ContentRemoved(nsIContent* aChild,
7288 nsIContent* aOldNextSibling,
7289 RemoveFlags aFlags) {
7290 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"
, 7290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 7290; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7291 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"
, 7292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7292; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7292 "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"
, 7292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aOldNextSibling"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7292; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7293 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentRemoved",mozilla::AutoProfilerLabelHot raiiObject7294( "nsCSSFrameConstructor::ContentRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7294 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7294( "nsCSSFrameConstructor::ContentRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7295 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7296 nsPresContext* presContext = mPresShell->GetPresContext();
7297 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"
, 7297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "presContext"
") (" "Our presShell should have a valid presContext" ")"); do
{ *((volatile int*)__null) = 7297; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7298
7299 // We want to detect when the viewport override element stored in the
7300 // prescontext is in the subtree being removed. Except in fullscreen cases
7301 // (which are handled in Element::UnbindFromTree and do not get stored on the
7302 // prescontext), the override element is always either the root element or a
7303 // <body> child of the root element. So we can only be removing the stored
7304 // override element if the thing being removed is either the override element
7305 // itself or the root element (which can be a parent of the override element).
7306 if (aChild == presContext->GetViewportScrollStylesOverrideElement() ||
7307 (aChild->IsElement() && !aChild->GetParent())) {
7308 // We might be removing the element that we propagated viewport scrollbar
7309 // styles from. Recompute those. (This clause covers two of the three
7310 // possible scrollbar-propagation sources: the <body> [as aChild or a
7311 // descendant] and the root node. The other possible scrollbar-propagation
7312 // source is a fullscreen element, and we have code elsewhere to update
7313 // scrollbars after fullscreen elements are removed -- specifically, it's
7314 // part of the fullscreen cleanup code called by Element::UnbindFromTree.
7315 // We don't handle the fullscreen case here, because it doesn't change the
7316 // scrollbar styles override element stored on the prescontext.)
7317 Element* newOverrideElement =
7318 presContext->UpdateViewportScrollStylesOverride();
7319
7320 // If aChild is the root, then we don't need to do any reframing of
7321 // newOverrideElement, because we're about to tear down the whole frame tree
7322 // anyway. And we need to make sure we don't do any such reframing, because
7323 // reframing the <body> can trigger a reframe of the <html> and then reenter
7324 // here.
7325 //
7326 // But if aChild is not the root, and if newOverrideElement is not
7327 // the root and isn't aChild (which it could be if all we're doing
7328 // here is reframing the current override element), it needs
7329 // reframing. In particular, it used to have a scrollframe
7330 // (because its overflow was not "visible"), but now it will
7331 // propagate its overflow to the viewport, so it should not need a
7332 // scrollframe anymore.
7333 if (aChild->GetParent() && newOverrideElement &&
7334 newOverrideElement->GetParent() && newOverrideElement != aChild) {
7335 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7336 RecreateFramesForContent(newOverrideElement, InsertionKind::Async);
7337 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7338 }
7339 }
7340
7341#ifdef DEBUG1
7342 if (gNoisyContentUpdates) {
7343 printf(
7344 "nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
7345 "old-next-sibling=%p\n",
7346 aChild->GetParent(), aChild, aOldNextSibling);
7347 if (gReallyNoisyContentUpdates) {
7348 aChild->GetParent()->List(stdoutstdout, 0);
7349 }
7350 }
7351#endif
7352
7353 nsIFrame* childFrame = aChild->GetPrimaryFrame();
7354 if (!childFrame || childFrame->GetContent() != aChild) {
7355 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7356 // Remove it once that's fixed.
7357 childFrame = nullptr;
7358 }
7359
7360 // If we're removing the root, then make sure to remove things starting at
7361 // the viewport's child instead of the primary frame (which might even be
7362 // null if the root was display:none, even though the frames above it got
7363 // created). Detecting removal of a root is a little exciting; in particular,
7364 // having no parent is necessary but NOT sufficient.
7365 //
7366 // Due to how we process reframes, the content node might not even be in our
7367 // document by now. So explicitly check whether the viewport's first kid's
7368 // content node is aChild.
7369 //
7370 // FIXME(emilio): I think the "might not be in our document" bit is impossible
7371 // now.
7372 bool isRoot = false;
7373 if (!aChild->GetParent()) {
7374 if (nsIFrame* viewport = GetRootFrame()) {
7375 nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
7376 if (firstChild && firstChild->GetContent() == aChild) {
7377 isRoot = true;
7378 childFrame = firstChild;
7379 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"
, 7379); MOZ_PretendNoReturn(); } } while (0)
;
7380 }
7381 }
7382 }
7383
7384 // We need to be conservative about when to determine whether something has
7385 // display: contents or not because at this point our actual display may be
7386 // different.
7387 //
7388 // Consider the case of:
7389 //
7390 // <div id="A" style="display: contents"><div id="B"></div></div>
7391 //
7392 // If we reconstruct A because its display changed to "none", we still need to
7393 // cleanup the frame on B, but A's display is now "none", so we can't poke at
7394 // the style of it.
7395 //
7396 // FIXME(emilio, bug 1450366): We can make this faster without adding much
7397 // complexity for the display: none -> other case, which right now
7398 // unnecessarily walks the content tree down.
7399 auto CouldHaveBeenDisplayContents = [aFlags](nsIContent* aContent) -> bool {
7400 return aFlags == REMOVE_FOR_RECONSTRUCTION || IsDisplayContents(aContent);
7401 };
7402
7403 if (!childFrame && CouldHaveBeenDisplayContents(aChild)) {
7404 // NOTE(emilio): We may iterate through ::before and ::after here and they
7405 // may be gone after the respective ContentRemoved call. Right now
7406 // StyleChildrenIterator handles that properly, so it's not an issue.
7407 StyleChildrenIterator iter(aChild);
7408 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
7409 if (c->GetPrimaryFrame() || CouldHaveBeenDisplayContents(c)) {
7410 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7411 bool didReconstruct = ContentRemoved(c, nullptr, aFlags);
7412 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7413 if (didReconstruct) {
7414 return true;
7415 }
7416 }
7417 }
7418 return false;
7419 }
7420
7421 if (childFrame) {
7422 if (aFlags == REMOVE_FOR_RECONSTRUCTION) {
7423 // Before removing the frames associated with the content object,
7424 // ask them to save their state onto our state object.
7425 CaptureStateForFramesOf(aChild, mFrameTreeState);
7426 }
7427
7428 InvalidateCanvasIfNeeded(mPresShell, aChild);
7429
7430 // See whether we need to remove more than just childFrame
7431 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7432 if (MaybeRecreateContainerForFrameRemoval(childFrame)) {
7433 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7434 return true;
7435 }
7436 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7437
7438 // Get the childFrame's parent frame
7439 nsIFrame* parentFrame = childFrame->GetParent();
7440 LayoutFrameType parentType = parentFrame->Type();
7441
7442 if (parentType == LayoutFrameType::FrameSet &&
7443 IsSpecialFramesetChild(aChild)) {
7444 // Just reframe the parent, since framesets are weird like that.
7445 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7446 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7447 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7448 return true;
7449 }
7450
7451 // If we're a child of MathML, then we should reframe the MathML content.
7452 // If we're non-MathML, then we would be wrapped in a block so we need to
7453 // check our grandparent in that case.
7454 nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
7455 ? parentFrame->GetParent()
7456 : parentFrame;
7457 if (possibleMathMLAncestor->IsMathMLFrame()) {
7458 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7459 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7460 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7461 return true;
7462 }
7463
7464#ifdef ACCESSIBILITY1
7465 if (aFlags != REMOVE_FOR_RECONSTRUCTION) {
7466 if (nsAccessibilityService* accService = GetAccService()) {
7467 accService->ContentRemoved(mPresShell, aChild);
7468 }
7469 }
7470#endif
7471
7472 // Examine the containing-block for the removed content and see if
7473 // :first-letter style applies.
7474 nsIFrame* inflowChild = childFrame;
7475 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7476 inflowChild = childFrame->GetPlaceholderFrame();
7477 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"
, 7477); MOZ_PretendNoReturn(); } } while (0)
;
7478 }
7479 nsContainerFrame* containingBlock =
7480 GetFloatContainingBlock(inflowChild->GetParent());
7481 bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
7482 if (haveFLS) {
7483 // Trap out to special routine that handles adjusting a blocks
7484 // frame tree when first-letter style is present.
7485#ifdef NOISY_FIRST_LETTER
7486 printf("ContentRemoved: containingBlock=");
7487 containingBlock->ListTag(stdoutstdout);
7488 printf(" parentFrame=");
7489 parentFrame->ListTag(stdoutstdout);
7490 printf(" childFrame=");
7491 childFrame->ListTag(stdoutstdout);
7492 printf("\n");
7493#endif
7494
7495 // First update the containing blocks structure by removing the
7496 // existing letter frames. This makes the subsequent logic
7497 // simpler.
7498 RemoveLetterFrames(mPresShell, containingBlock);
7499
7500 // Recover childFrame and parentFrame
7501 childFrame = aChild->GetPrimaryFrame();
7502 if (!childFrame || childFrame->GetContent() != aChild) {
7503 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7504 // Remove it once that's fixed.
7505 return false;
7506 }
7507 parentFrame = childFrame->GetParent();
7508 parentType = parentFrame->Type();
Value stored to 'parentType' is never read
7509
7510#ifdef NOISY_FIRST_LETTER
7511 printf(" ==> revised parentFrame=");
7512 parentFrame->ListTag(stdoutstdout);
7513 printf(" childFrame=");
7514 childFrame->ListTag(stdoutstdout);
7515 printf("\n");
7516#endif
7517 }
7518
7519#ifdef DEBUG1
7520 if (gReallyNoisyContentUpdates) {
7521 printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
7522 childFrame->ListTag(stdoutstdout);
7523 putchar('\n');
7524 parentFrame->List(stdoutstdout);
7525 }
7526#endif
7527
7528 // Notify the parent frame that it should delete the frame
7529 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7530 childFrame = childFrame->GetPlaceholderFrame();
7531 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"
, 7531); MOZ_PretendNoReturn(); } } while (0)
;
7532 parentFrame = childFrame->GetParent();
7533 }
7534
7535 // Take care of wrapper anonymous boxes that we might need to remove while
7536 // at it. Note that MaybeRecreateContainerForFrameRemoval takes care of
7537 // harder cases (merging sibling anonymous boxes etc).
7538 while (IsWrapperPseudo(parentFrame) &&
7539 CanRemoveWrapperPseudoForChildRemoval(childFrame, parentFrame)) {
7540 childFrame = parentFrame;
7541 parentFrame = childFrame->GetParent();
7542 }
7543
7544 DestroyContext context(mPresShell);
7545 RemoveFrame(context, nsLayoutUtils::GetChildListNameFor(childFrame),
7546 childFrame);
7547
7548 // NOTE(emilio): aChild could be dead here already if it is a ::before or
7549 // ::after pseudo-element (since in that case it was owned by childFrame,
7550 // which we just destroyed).
7551
7552 if (isRoot) {
7553 mRootElementFrame = nullptr;
7554 mRootElementStyleFrame = nullptr;
7555 mDocElementContainingBlock = nullptr;
7556 mCanvasFrame = nullptr;
7557 mPageSequenceFrame = nullptr;
7558 }
7559
7560 if (haveFLS && mRootElementFrame) {
7561 RecoverLetterFrames(containingBlock);
7562 }
7563
7564 // If we're just reconstructing frames for the element, then the
7565 // following ContentInserted notification on the element will
7566 // take care of fixing up any adjacent text nodes.
7567 if (aOldNextSibling && aFlags == REMOVE_CONTENT) {
7568 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"
, 7569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7569; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7569 "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"
, 7569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7569; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7570 // Adjacent whitespace-only text nodes might have been suppressed if
7571 // this node does not have inline ends. Create frames for them now
7572 // if necessary.
7573 // Reframe any text node just before the node being removed, if there is
7574 // one, and if it's not the last child or the first child. If a whitespace
7575 // textframe was being suppressed and it's now the last child or first
7576 // child then it can stay suppressed since the parent must be a block
7577 // and hence it's adjacent to a block end.
7578 // If aOldNextSibling is null, then the text node before the node being
7579 // removed is the last node, and we don't need to worry about it.
7580 nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
7581 if (prevSibling && prevSibling->GetPreviousSibling()) {
7582 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7583 ReframeTextIfNeeded(prevSibling);
7584 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7585 }
7586 // Reframe any text node just after the node being removed, if there is
7587 // one, and if it's not the last child or the first child.
7588 if (aOldNextSibling->GetNextSibling() &&
7589 aOldNextSibling->GetPreviousSibling()) {
7590 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7591 ReframeTextIfNeeded(aOldNextSibling);
7592 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7593 }
7594 }
7595
7596#ifdef DEBUG1
7597 if (gReallyNoisyContentUpdates && parentFrame) {
7598 printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
7599 parentFrame->List(stdoutstdout);
7600 }
7601#endif
7602 }
7603
7604 return false;
7605}
7606
7607/**
7608 * This method invalidates the canvas when frames are removed or added for a
7609 * node that might have its background propagated to the canvas, i.e., a
7610 * document root node or an HTML BODY which is a child of the root node.
7611 *
7612 * @param aFrame a frame for a content node about to be removed or a frame that
7613 * was just created for a content node that was inserted.
7614 */
7615static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode) {
7616 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"
, 7616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetRootFrame()"
") (" "What happened here?" ")"); do { *((volatile int*)__null
) = 7616; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
7617 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"
, 7617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetPresContext()"
") (" "Say what?" ")"); do { *((volatile int*)__null) = 7617
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7618
7619 // Note that both in ContentRemoved and ContentInserted the content node
7620 // will still have the right parent pointer, so looking at that is ok.
7621
7622 nsIContent* parent = aNode->GetParent();
7623 if (parent) {
7624 // Has a parent; might not be what we want
7625 nsIContent* grandParent = parent->GetParent();
7626 if (grandParent) {
7627 // Has a grandparent, so not what we want
7628 return;
7629 }
7630
7631 // Check whether it's an HTML body
7632 if (!aNode->IsHTMLElement(nsGkAtoms::body)) {
7633 return;
7634 }
7635 }
7636
7637 // At this point the node has no parent or it's an HTML <body> child of the
7638 // root. We might not need to invalidate in this case (eg we might be in
7639 // XHTML or something), but chances are we want to. Play it safe.
7640 // Invalidate the viewport.
7641
7642 nsIFrame* rootFrame = aPresShell->GetRootFrame();
7643 rootFrame->InvalidateFrameSubtree();
7644}
7645
7646bool nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
7647 CharacterData* aContent) {
7648 if (!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
7649 return false;
7650 }
7651
7652 if (mAlwaysCreateFramesForIgnorableWhitespace) {
7653 return false;
7654 }
7655
7656 // Text frame may have been suppressed. Disable suppression and signal that a
7657 // flush should be performed. We do this on a document-wide basis so that
7658 // pages that repeatedly query metrics for collapsed-whitespace text nodes
7659 // don't trigger pathological behavior.
7660 mAlwaysCreateFramesForIgnorableWhitespace = true;
7661 Element* root = mDocument->GetRootElement();
7662 if (!root) {
7663 return false;
7664 }
7665
7666 RestyleManager()->PostRestyleEvent(root, RestyleHint{0},
7667 nsChangeHint_ReconstructFrame);
7668 return true;
7669}
7670
7671void nsCSSFrameConstructor::CharacterDataChanged(
7672 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) {
7673 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::CharacterDataChanged",mozilla::AutoProfilerLabelHot raiiObject7674( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7674 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7674( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7675 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7676
7677 if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
7678 !aContent->TextIsOnlyWhitespace()) ||
7679 (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
7680 aContent->TextIsOnlyWhitespace())) {
7681#ifdef DEBUG1
7682 nsIFrame* frame = aContent->GetPrimaryFrame();
7683 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"
, 7684); MOZ_PretendNoReturn(); } } while (0)
7684 "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"
, 7684); MOZ_PretendNoReturn(); } } while (0)
;
7685#endif
7686 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7687 RecreateFramesForContent(aContent, InsertionKind::Async);
7688 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7689 return;
7690 }
7691
7692 // It's possible the frame whose content changed isn't inserted into the
7693 // frame hierarchy yet, or that there is no frame that maps the content
7694 if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
7695#if 0
7696 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)
7697 ("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)
7698 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)
7699 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)
;
7700#endif
7701
7702 if (frame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) {
7703 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7704 RecreateFramesForContent(aContent, InsertionKind::Async);
7705 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7706 return;
7707 }
7708
7709 // Special check for text content that is a child of a letter frame. If
7710 // this happens, we should remove the letter frame, do whatever we're
7711 // planning to do with this notification, then put the letter frame back.
7712 // Note that this is basically what RecreateFramesForContent ends up doing;
7713 // the reason we dont' want to call that here is that our text content
7714 // could be native anonymous, in which case RecreateFramesForContent would
7715 // completely barf on it. And recreating the non-anonymous ancestor would
7716 // just lead us to come back into this notification (e.g. if quotes or
7717 // counters are involved), leading to a loop.
7718 nsContainerFrame* block = GetFloatContainingBlock(frame);
7719 bool haveFirstLetterStyle = false;
7720 if (block) {
7721 // See if the block has first-letter style applied to it.
7722 haveFirstLetterStyle = HasFirstLetterStyle(block);
7723 if (haveFirstLetterStyle) {
7724 RemoveLetterFrames(mPresShell, block);
7725 // Reget |frame|, since we might have killed it.
7726 // Do we really need to call CharacterDataChanged in this case, though?
7727 frame = aContent->GetPrimaryFrame();
7728 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"
, 7728); MOZ_PretendNoReturn(); } } while (0)
;
7729 }
7730 }
7731
7732 // Notify the first frame that maps the content. It will generate a reflow
7733 // command
7734 frame->CharacterDataChanged(aInfo);
7735
7736 if (haveFirstLetterStyle) {
7737 RecoverLetterFrames(block);
7738 }
7739 }
7740}
7741
7742void nsCSSFrameConstructor::RecalcQuotesAndCounters() {
7743 nsAutoScriptBlocker scriptBlocker;
7744
7745 if (mQuotesDirty) {
7746 mQuotesDirty = false;
7747 mContainStyleScopeManager.RecalcAllQuotes();
7748 }
7749
7750 if (mCountersDirty) {
7751 mCountersDirty = false;
7752 mContainStyleScopeManager.RecalcAllCounters();
7753 }
7754
7755 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"
, 7755); MOZ_PretendNoReturn(); } } while (0)
;
7756 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"
, 7756); MOZ_PretendNoReturn(); } } while (0)
;
7757}
7758
7759void nsCSSFrameConstructor::NotifyCounterStylesAreDirty() {
7760 mContainStyleScopeManager.SetAllCountersDirty();
7761 CountersDirty();
7762}
7763
7764void nsCSSFrameConstructor::WillDestroyFrameTree() {
7765#if defined(DEBUG_dbaron_off)
7766 mContainStyleScopeManager.DumpCounters();
7767#endif
7768
7769 // Prevent frame tree destruction from being O(N^2)
7770 mContainStyleScopeManager.Clear();
7771 nsFrameManager::Destroy();
7772}
7773
7774// STATIC
7775
7776// XXXbz I'd really like this method to go away. Once we have inline-block and
7777// I can just use that for sized broken images, that can happen, maybe.
7778//
7779// NOTE(emilio): This needs to match MozAltContent handling.
7780void nsCSSFrameConstructor::GetAlternateTextFor(const Element& aElement,
7781 nsAString& aAltText) {
7782 // The "alt" attribute specifies alternate text that is rendered
7783 // when the image can not be displayed.
7784 if (aElement.GetAttr(nsGkAtoms::alt, aAltText)) {
7785 return;
7786 }
7787
7788 if (aElement.IsHTMLElement(nsGkAtoms::input)) {
7789 // If there's no "alt" attribute, and aElement is an input element, then use
7790 // the value of the "value" attribute.
7791 if (aElement.GetAttr(nsGkAtoms::value, aAltText)) {
7792 return;
7793 }
7794
7795 // If there's no "value" attribute either, then use the localized string for
7796 // "Submit" as the alternate text.
7797 nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
7798 "Submit", aElement.OwnerDoc(),
7799 aAltText);
7800 }
7801}
7802
7803nsIFrame* nsCSSFrameConstructor::CreateContinuingOuterTableFrame(
7804 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7805 ComputedStyle* aComputedStyle) {
7806 nsTableWrapperFrame* newFrame =
7807 NS_NewTableWrapperFrame(mPresShell, aComputedStyle);
7808
7809 newFrame->Init(aContent, aParentFrame, aFrame);
7810
7811 // Create a continuing inner table frame, and if there's a caption then
7812 // replicate the caption
7813 nsFrameList newChildFrames;
7814
7815 nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
7816 if (childFrame) {
7817 nsIFrame* continuingTableFrame =
7818 CreateContinuingFrame(childFrame, newFrame);
7819 newChildFrames.AppendFrame(nullptr, continuingTableFrame);
7820
7821 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"
, 7822); MOZ_PretendNoReturn(); } } while (0)
7822 "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"
, 7822); MOZ_PretendNoReturn(); } } while (0)
;
7823 }
7824
7825 // Set the table wrapper's initial child list
7826 newFrame->SetInitialChildList(FrameChildListID::Principal,
7827 std::move(newChildFrames));
7828
7829 return newFrame;
7830}
7831
7832nsIFrame* nsCSSFrameConstructor::CreateContinuingTableFrame(
7833 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7834 ComputedStyle* aComputedStyle) {
7835 nsTableFrame* newFrame = NS_NewTableFrame(mPresShell, aComputedStyle);
7836
7837 newFrame->Init(aContent, aParentFrame, aFrame);
7838
7839 // Replicate any header/footer frames
7840 nsFrameList childFrames;
7841 for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
7842 // See if it's a header/footer, possibly wrapped in a scroll frame.
7843 nsTableRowGroupFrame* rowGroupFrame =
7844 static_cast<nsTableRowGroupFrame*>(childFrame);
7845 // If the row group was continued, then don't replicate it.
7846 nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
7847 if (rgNextInFlow) {
7848 rowGroupFrame->SetRepeatable(false);
7849 } else if (rowGroupFrame->IsRepeatable()) {
7850 // Replicate the header/footer frame.
7851 nsTableRowGroupFrame* headerFooterFrame;
7852 nsFrameList childList;
7853
7854 nsFrameConstructorState state(
7855 mPresShell, GetAbsoluteContainingBlock(newFrame, FIXED_POS),
7856 GetAbsoluteContainingBlock(newFrame, ABS_POS), nullptr);
7857 state.mCreatingExtraFrames = true;
7858
7859 ComputedStyle* const headerFooterComputedStyle = rowGroupFrame->Style();
7860 headerFooterFrame = static_cast<nsTableRowGroupFrame*>(
7861 NS_NewTableRowGroupFrame(mPresShell, headerFooterComputedStyle));
7862
7863 nsIContent* headerFooter = rowGroupFrame->GetContent();
7864 headerFooterFrame->Init(headerFooter, newFrame, nullptr);
7865
7866 nsFrameConstructorSaveState absoluteSaveState;
7867 MakeTablePartAbsoluteContainingBlock(state, absoluteSaveState,
7868 headerFooterFrame);
7869
7870 nsFrameConstructorSaveState floatSaveState;
7871 state.MaybePushFloatContainingBlock(headerFooterFrame, floatSaveState);
7872
7873 ProcessChildren(state, headerFooter, rowGroupFrame->Style(),
7874 headerFooterFrame, true, childList, false, nullptr);
7875 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"
, 7875); MOZ_PretendNoReturn(); } } while (0)
;
7876 headerFooterFrame->SetInitialChildList(FrameChildListID::Principal,
7877 std::move(childList));
7878 headerFooterFrame->SetRepeatable(true);
7879
7880 // Table specific initialization
7881 headerFooterFrame->InitRepeatedFrame(rowGroupFrame);
7882
7883 // XXX Deal with absolute and fixed frames...
7884 childFrames.AppendFrame(nullptr, headerFooterFrame);
7885 }
7886 }
7887
7888 // Set the table frame's initial child list
7889 newFrame->SetInitialChildList(FrameChildListID::Principal,
7890 std::move(childFrames));
7891
7892 return newFrame;
7893}
7894
7895nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
7896 nsIFrame* aFrame, nsContainerFrame* aParentFrame, bool aIsFluid) {
7897 ComputedStyle* computedStyle = aFrame->Style();
7898 nsIFrame* newFrame = nullptr;
7899 nsIFrame* nextContinuation = aFrame->GetNextContinuation();
7900 nsIFrame* nextInFlow = aFrame->GetNextInFlow();
7901
7902 // Use the frame type to determine what type of frame to create
7903 LayoutFrameType frameType = aFrame->Type();
7904 nsIContent* content = aFrame->GetContent();
7905
7906 if (LayoutFrameType::Text == frameType) {
7907 newFrame = NS_NewContinuingTextFrame(mPresShell, computedStyle);
7908 newFrame->Init(content, aParentFrame, aFrame);
7909 } else if (LayoutFrameType::Inline == frameType) {
7910 newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
7911 newFrame->Init(content, aParentFrame, aFrame);
7912 } else if (LayoutFrameType::Block == frameType) {
7913 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"
, 7914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7914; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7914 "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"
, 7914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7914; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7915 newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
7916 newFrame->Init(content, aParentFrame, aFrame);
7917 } else if (LayoutFrameType::ColumnSetWrapper == frameType) {
7918 newFrame =
7919 NS_NewColumnSetWrapperFrame(mPresShell, computedStyle, nsFrameState(0));
7920 newFrame->Init(content, aParentFrame, aFrame);
7921 } else if (LayoutFrameType::ColumnSet == frameType) {
7922 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"
, 7923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7923; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7923 "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"
, 7923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7923; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7924 newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
7925 newFrame->Init(content, aParentFrame, aFrame);
7926 } else if (LayoutFrameType::PrintedSheet == frameType) {
7927 newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
7928 } else if (LayoutFrameType::Page == frameType) {
7929 nsCanvasFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
7930 newFrame =
7931 ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
7932 } else if (LayoutFrameType::TableWrapper == frameType) {
7933 newFrame = CreateContinuingOuterTableFrame(aFrame, aParentFrame, content,
7934 computedStyle);
7935 } else if (LayoutFrameType::Table == frameType) {
7936 newFrame = CreateContinuingTableFrame(aFrame, aParentFrame, content,
7937 computedStyle);
7938 } else if (LayoutFrameType::TableRowGroup == frameType) {
7939 newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
7940 newFrame->Init(content, aParentFrame, aFrame);
7941 } else if (LayoutFrameType::TableRow == frameType) {
7942 nsTableRowFrame* rowFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
7943
7944 rowFrame->Init(content, aParentFrame, aFrame);
7945
7946 // Create a continuing frame for each table cell frame
7947 nsFrameList newChildList;
7948 nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
7949 while (cellFrame) {
7950 // See if it's a table cell frame
7951 if (cellFrame->IsTableCellFrame()) {
7952 nsIFrame* continuingCellFrame =
7953 CreateContinuingFrame(cellFrame, rowFrame);
7954 newChildList.AppendFrame(nullptr, continuingCellFrame);
7955 }
7956 cellFrame = cellFrame->GetNextSibling();
7957 }
7958
7959 rowFrame->SetInitialChildList(FrameChildListID::Principal,
7960 std::move(newChildList));
7961 newFrame = rowFrame;
7962
7963 } else if (LayoutFrameType::TableCell == frameType) {
7964 // Warning: If you change this and add a wrapper frame around table cell
7965 // frames, make sure Bug 368554 doesn't regress!
7966 // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
7967 nsTableFrame* tableFrame =
7968 static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
7969 nsTableCellFrame* cellFrame =
7970 NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
7971
7972 cellFrame->Init(content, aParentFrame, aFrame);
7973
7974 // Create a continuing area frame
7975 nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
7976 nsIFrame* continuingBlockFrame =
7977 CreateContinuingFrame(blockFrame, cellFrame);
7978
7979 SetInitialSingleChild(cellFrame, continuingBlockFrame);
7980 newFrame = cellFrame;
7981 } else if (LayoutFrameType::Line == frameType) {
7982 newFrame = NS_NewFirstLineFrame(mPresShell, computedStyle);
7983 newFrame->Init(content, aParentFrame, aFrame);
7984 } else if (LayoutFrameType::Letter == frameType) {
7985 newFrame = NS_NewFirstLetterFrame(mPresShell, computedStyle);
7986 newFrame->Init(content, aParentFrame, aFrame);
7987 } else if (LayoutFrameType::Image == frameType) {
7988 auto* imageFrame = static_cast<nsImageFrame*>(aFrame);
7989 newFrame = imageFrame->CreateContinuingFrame(mPresShell, computedStyle);
7990 newFrame->Init(content, aParentFrame, aFrame);
7991 } else if (LayoutFrameType::ImageControl == frameType) {
7992 newFrame = NS_NewImageControlFrame(mPresShell, computedStyle);
7993 newFrame->Init(content, aParentFrame, aFrame);
7994 } else if (LayoutFrameType::FieldSet == frameType) {
7995 newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
7996 newFrame->Init(content, aParentFrame, aFrame);
7997 } else if (LayoutFrameType::FlexContainer == frameType) {
7998 newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
7999 newFrame->Init(content, aParentFrame, aFrame);
8000 } else if (LayoutFrameType::GridContainer == frameType) {
8001 newFrame = NS_NewGridContainerFrame(mPresShell, computedStyle);
8002 newFrame->Init(content, aParentFrame, aFrame);
8003 } else if (LayoutFrameType::Ruby == frameType) {
8004 newFrame = NS_NewRubyFrame(mPresShell, computedStyle);
8005 newFrame->Init(content, aParentFrame, aFrame);
8006 } else if (LayoutFrameType::RubyBaseContainer == frameType) {
8007 newFrame = NS_NewRubyBaseContainerFrame(mPresShell, computedStyle);
8008 newFrame->Init(content, aParentFrame, aFrame);
8009 } else if (LayoutFrameType::RubyTextContainer == frameType) {
8010 newFrame = NS_NewRubyTextContainerFrame(mPresShell, computedStyle);
8011 newFrame->Init(content, aParentFrame, aFrame);
8012 } else {
8013 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"
, 8013); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected frame type"
")"); do { *((volatile int*)__null) = 8013; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
8014 }
8015
8016 // Init() set newFrame to be a fluid continuation of aFrame.
8017 // If we want a non-fluid continuation, we need to call SetPrevContinuation()
8018 // to reset NS_FRAME_IS_FLUID_CONTINUATION.
8019 if (!aIsFluid) {
8020 newFrame->SetPrevContinuation(aFrame);
8021 }
8022
8023 // If a continuing frame needs to carry frame state bits from its previous
8024 // continuation or parent, set them in nsIFrame::Init(), or in any derived
8025 // frame class's Init() if the bits are belong to specific group.
8026
8027 if (nextInFlow) {
8028 nextInFlow->SetPrevInFlow(newFrame);
8029 newFrame->SetNextInFlow(nextInFlow);
8030 } else if (nextContinuation) {
8031 nextContinuation->SetPrevContinuation(newFrame);
8032 newFrame->SetNextContinuation(nextContinuation);
8033 }
8034
8035 // aFrame cannot be a dynamic reflow root because it has a continuation now.
8036 aFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
8037
8038 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"
, 8038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newFrame->GetNextSibling()"
") (" "unexpected sibling" ")"); do { *((volatile int*)__null
) = 8038; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8039 return newFrame;
8040}
8041
8042void nsCSSFrameConstructor::MaybeSetNextPageContentFramePageName(
8043 const nsIFrame* aFrame) {
8044 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"
, 8044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Frame should not be null" ")"); do { *((volatile int*)__null
) = 8044; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8045 // No parent means the root frame, which isn't what this funciton is for.
8046 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"
, 8048); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8048; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8047 "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"
, 8048); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8048; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8048 "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"
, 8048); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8048; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8049 if (mNextPageContentFramePageName) {
8050 return;
8051 }
8052 const nsAtom* const autoValue = aFrame->GetParent()->GetAutoPageValue();
8053 mNextPageContentFramePageName = aFrame->ComputePageValue(autoValue);
8054}
8055
8056nsresult nsCSSFrameConstructor::ReplicateFixedFrames(
8057 nsPageContentFrame* aParentFrame) {
8058 // Now deal with fixed-pos things.... They should appear on all pages,
8059 // so we want to move over the placeholders when processing the child
8060 // of the pageContentFrame.
8061
8062 nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
8063 if (!prevPageContentFrame) {
8064 return NS_OK;
8065 }
8066 nsContainerFrame* canvasFrame =
8067 do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
8068 nsIFrame* prevCanvasFrame =
8069 prevPageContentFrame->PrincipalChildList().FirstChild();
8070 if (!canvasFrame || !prevCanvasFrame) {
8071 // document's root element frame missing
8072 return NS_ERROR_UNEXPECTED;
8073 }
8074
8075 nsFrameList fixedPlaceholders;
8076 nsIFrame* firstFixed =
8077 prevPageContentFrame->GetChildList(FrameChildListID::Fixed).FirstChild();
8078 if (!firstFixed) {
8079 return NS_OK;
8080 }
8081
8082 // Don't allow abs-pos descendants of the fixed content to escape the content.
8083 // This should not normally be possible (because fixed-pos elements should
8084 // be absolute containers) but fixed-pos tables currently aren't abs-pos
8085 // containers.
8086 nsFrameConstructorState state(mPresShell, aParentFrame, nullptr,
8087 mRootElementFrame);
8088 state.mCreatingExtraFrames = true;
8089
8090 // We can't use an ancestor filter here, because we're not going to
8091 // be usefully recurring down the tree. This means that other
8092 // places in frame construction can't assume a filter is
8093 // initialized!
8094
8095 // Iterate across fixed frames and replicate each whose placeholder is a
8096 // descendant of aFrame. (We don't want to explicitly copy placeholders that
8097 // are within fixed frames, because that would cause duplicates on the new
8098 // page - bug 389619)
8099 for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
8100 nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame();
8101 if (prevPlaceholder && nsLayoutUtils::IsProperAncestorFrame(
8102 prevCanvasFrame, prevPlaceholder)) {
8103 // We want to use the same style as the primary style frame for
8104 // our content
8105 nsIContent* content = fixed->GetContent();
8106 ComputedStyle* computedStyle =
8107 nsLayoutUtils::GetStyleFrame(content)->Style();
8108 AutoFrameConstructionItemList items(this);
8109 AddFrameConstructionItemsInternal(state, content, canvasFrame, true,
8110 computedStyle,
8111 {ItemFlag::AllowPageBreak}, items);
8112 ConstructFramesFromItemList(state, items, canvasFrame,
8113 /* aParentIsWrapperAnonBox = */ false,
8114 fixedPlaceholders);
8115 }
8116 }
8117
8118 // Add the placeholders to our primary child list.
8119 // XXXbz this is a little screwed up, since the fixed frames will have
8120 // broken auto-positioning. Oh, well.
8121 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"
, 8122); MOZ_PretendNoReturn(); } } while (0)
8122 "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"
, 8122); MOZ_PretendNoReturn(); } } while (0)
;
8123 canvasFrame->SetInitialChildList(FrameChildListID::Principal,
8124 std::move(fixedPlaceholders));
8125 return NS_OK;
8126}
8127
8128nsCSSFrameConstructor::InsertionPoint nsCSSFrameConstructor::GetInsertionPoint(
8129 nsIContent* aChild) {
8130 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"
, 8130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 8130; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8131 nsIContent* insertionElement = aChild->GetFlattenedTreeParent();
8132 if (!insertionElement) {
8133 // The element doesn't belong in the flattened tree, and thus we don't want
8134 // to render it.
8135 return {};
8136 }
8137
8138 return {GetContentInsertionFrameFor(insertionElement), insertionElement};
8139}
8140
8141// Capture state for the frame tree rooted at the frame associated with the
8142// content object, aContent
8143void nsCSSFrameConstructor::CaptureStateForFramesOf(
8144 nsIContent* aContent, nsILayoutHistoryState* aHistoryState) {
8145 if (!aHistoryState) {
8146 return;
8147 }
8148 nsIFrame* frame = aContent->GetPrimaryFrame();
8149 if (frame == mRootElementFrame) {
8150 frame = mRootElementFrame
8151 ? GetAbsoluteContainingBlock(mRootElementFrame, FIXED_POS)
8152 : GetRootFrame();
8153 }
8154 for (; frame;
8155 frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
8156 CaptureFrameState(frame, aHistoryState);
8157 }
8158}
8159
8160static bool IsWhitespaceFrame(nsIFrame* aFrame) {
8161 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"
, 8161); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 8161
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8162 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
8163}
8164
8165static nsIFrame* FindNextNonWhitespaceSibling(nsIFrame* aFrame) {
8166 nsIFrame* f = aFrame;
8167 do {
8168 f = f->GetNextSibling();
8169 } while (f && IsWhitespaceFrame(f));
8170 return f;
8171}
8172
8173static nsIFrame* FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) {
8174 nsIFrame* f = aFrame;
8175 do {
8176 f = f->GetPrevSibling();
8177 } while (f && IsWhitespaceFrame(f));
8178 return f;
8179}
8180
8181bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
8182 nsIFrame* aFrame) {
8183#define TRACE(reason) \
8184 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)
8185 {}, 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)
8186 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"
, 8186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have a frame" ")"); do { *((volatile int*)__null) = 8186
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8187 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"
, 8187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame shouldn't be root" ")"); do { *((volatile int*)
__null) = 8187; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8188 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"
, 8189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8189; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8189 "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"
, 8189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8189; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8190
8191 nsIFrame* inFlowFrame = aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)
8192 ? aFrame->GetPlaceholderFrame()
8193 : aFrame;
8194 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"
, 8194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 8194; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8195 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"
, 8196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8196; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8196 "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"
, 8196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8196; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8197 nsIFrame* parent = inFlowFrame->GetParent();
8198
8199 if (inFlowFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
8200 nsIFrame* grandparent = parent->GetParent();
8201 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"
, 8201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "grandparent"
")"); do { *((volatile int*)__null) = 8201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8202
8203 bool needsReframe =
8204 // 1. Removing a column-span may lead to an empty
8205 // ::-moz-column-span-wrapper.
8206 inFlowFrame->IsColumnSpan() ||
8207 // 2. Removing a frame which has any column-span siblings may also
8208 // lead to an empty ::-moz-column-span-wrapper subtree. The
8209 // column-span siblings were the frame's children, but later become
8210 // the frame's siblings after CreateColumnSpanSiblings().
8211 inFlowFrame->HasColumnSpanSiblings() ||
8212 // 3. Removing the only child of a ::-moz-column-content, whose
8213 // ColumnSet grandparent has a previous column-span sibling, requires
8214 // reframing since we might connect the ColumnSet's next column-span
8215 // sibling (if there's one). Note that this isn't actually needed if
8216 // the ColumnSet is at the end of ColumnSetWrapper since we create
8217 // empty ones at the end anyway, but we're not worried about
8218 // optimizing that case.
8219 (parent->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
8220 // The only child in ::-moz-column-content (might be tall enough to
8221 // split across columns)
8222 !inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8223 // That ::-moz-column-content is the first column.
8224 !parent->GetPrevInFlow() &&
8225 // The ColumnSet grandparent has a previous sibling that is a
8226 // column-span.
8227 grandparent->GetPrevSibling());
8228
8229 if (needsReframe) {
8230 nsContainerFrame* containingBlock =
8231 GetMultiColumnContainingBlockFor(inFlowFrame);
8232
8233#ifdef DEBUG1
8234 if (IsFramePartOfIBSplit(inFlowFrame)) {
8235 nsIFrame* ibContainingBlock = GetIBContainingBlockFor(inFlowFrame);
8236 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"
, 8240); 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) = 8240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8237 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"
, 8240); 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) = 8240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8238 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"
, 8240); 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) = 8240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8239 "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"
, 8240); 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) = 8240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8240 "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"
, 8240); 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) = 8240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8241 }
8242#endif
8243
8244 TRACE("Multi-column");
8245 RecreateFramesForContent(containingBlock->GetContent(),
8246 InsertionKind::Async);
8247 return true;
8248 }
8249 }
8250
8251 if (IsFramePartOfIBSplit(aFrame)) {
8252 // The removal functions can't handle removal of an {ib} split directly; we
8253 // need to rebuild the containing block.
8254 TRACE("IB split removal");
8255 ReframeContainingBlock(aFrame);
8256 return true;
8257 }
8258
8259 if (inFlowFrame->IsRenderedLegend()) {
8260 TRACE("Fieldset / Legend");
8261 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8262 return true;
8263 }
8264
8265 // Might need to reconstruct things if this frame's nextSibling is a table
8266 // or ruby pseudo, since removal of this frame might mean that this pseudo
8267 // needs to get merged with the frame's prevSibling if that's also a table
8268 // or ruby pseudo.
8269 nsIFrame* nextSibling =
8270 FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
8271 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"
, 8272); MOZ_PretendNoReturn(); } } while (0)
8272 "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"
, 8272); MOZ_PretendNoReturn(); } } while (0)
;
8273 // Effectively, for the ruby pseudo sibling case, only pseudo <ruby> frame
8274 // need to be checked here, since all other types of such frames will have
8275 // a ruby container parent, and be catched by "Check ruby containers" below.
8276 if (nextSibling && IsWrapperPseudo(nextSibling)) {
8277 nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
8278 if (prevSibling && IsWrapperPseudo(prevSibling)) {
8279 TRACE("Pseudo sibling");
8280 // Good enough to recreate frames for aFrame's parent's content; even if
8281 // aFrame's parent is a pseudo, that'll be the right content node.
8282 // FIXME(emilio): Consider doing a more subtle check here like, only if
8283 // prevSibling and nextSibling share frame type. Or even consider just
8284 // moving the frames around and destroying nextSibling?
8285 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8286 return true;
8287 }
8288 }
8289
8290 // Check ruby containers
8291 LayoutFrameType parentType = parent->Type();
8292 if (parentType == LayoutFrameType::Ruby ||
8293 RubyUtils::IsRubyContainerBox(parentType)) {
8294 // In ruby containers, pseudo frames may be created from
8295 // whitespaces or even nothing. There are two cases we actually
8296 // need to handle here, but hard to check exactly:
8297 // 1. Status of spaces beside the frame may vary, and related
8298 // frames may be constructed or destroyed accordingly.
8299 // 2. The type of the first child of a ruby frame determines
8300 // whether a pseudo ruby base container should exist.
8301 TRACE("Ruby container");
8302 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8303 return true;
8304 }
8305
8306 // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
8307 // a non-fluid continuation, i.e. it was split by bidi resolution
8308 if (!inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8309 ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
8310 (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
8311 TRACE("Removing last child of non-fluid split parent");
8312 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8313 return true;
8314 }
8315
8316 // We might still need to reconstruct things if the parent of inFlowFrame is
8317 // ib-split, since in that case the removal of aFrame might affect the
8318 // splitting of its parent.
8319 if (!IsFramePartOfIBSplit(parent)) {
8320 return false;
8321 }
8322
8323 // If inFlowFrame is not the only in-flow child of |parent|, then removing
8324 // it will change nothing about the {ib} split.
8325 if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
8326 inFlowFrame->LastContinuation()->GetNextSibling()) {
8327 return false;
8328 }
8329
8330 // If the parent is the first or last part of the {ib} split, then
8331 // removing one of its kids will have no effect on the splitting.
8332 // Get the first continuation up front so we don't have to do it twice.
8333 nsIFrame* parentFirstContinuation = parent->FirstContinuation();
8334 if (!GetIBSplitSibling(parentFirstContinuation) ||
8335 !GetIBSplitPrevSibling(parentFirstContinuation)) {
8336 return false;
8337 }
8338
8339 TRACE("IB split parent");
8340 ReframeContainingBlock(parent);
8341 return true;
8342#undef TRACE
8343}
8344
8345void nsCSSFrameConstructor::UpdateTableCellSpans(nsIContent* aContent) {
8346 nsTableCellFrame* cellFrame = do_QueryFrame(aContent->GetPrimaryFrame());
8347
8348 // It's possible that this warning could fire if some other style change
8349 // simultaneously changes the 'display' of the element and makes it no
8350 // longer be a table cell.
8351 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"
, 8351); } } while (false)
;
8352
8353 if (cellFrame) {
8354 cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
8355 }
8356}
8357
8358static nsIContent* GetTopmostMathMLElement(nsIContent* aMathMLContent) {
8359 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"
, 8359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->IsMathMLElement()"
")"); do { *((volatile int*)__null) = 8359; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8360 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"
, 8360); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()"
")"); do { *((volatile int*)__null) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8361 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"
, 8361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()->IsMathMLFrame()"
")"); do { *((volatile int*)__null) = 8361; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8362 nsIContent* root = aMathMLContent;
8363
8364 for (nsIContent* parent = aMathMLContent->GetFlattenedTreeParent(); parent;
8365 parent = parent->GetFlattenedTreeParent()) {
8366 nsIFrame* frame = parent->GetPrimaryFrame();
8367 if (!frame || !frame->IsMathMLFrame()) {
8368 break;
8369 }
8370 root = parent;
8371 }
8372
8373 return root;
8374}
8375
8376// We don't know how to re-insert an anonymous subtree root, so recreate the
8377// closest non-generated ancestor instead, except for a few special cases...
8378static bool ShouldRecreateContainerForNativeAnonymousContentRoot(
8379 nsIContent* aContent) {
8380 if (!aContent->IsRootOfNativeAnonymousSubtree()) {
8381 return false;
8382 }
8383 if (ManualNACPtr::IsManualNAC(aContent)) {
8384 // Editor NAC, would enter an infinite loop, and we sorta get away with it
8385 // because it's all abspos.
8386 return false;
8387 }
8388 if (auto* el = Element::FromNode(aContent)) {
8389 if (auto* classes = el->GetClasses()) {
8390 if (classes->Contains(nsGkAtoms::mozCustomContentContainer,
8391 eCaseMatters)) {
8392 // Canvas anonymous content (like the custom content container) is also
8393 // fine, because its only sibling is a tooltip which is also abspos, so
8394 // relative insertion order doesn't really matter.
8395 //
8396 // This is important because the inspector uses it, and we don't want
8397 // inspecting the page to change behavior heavily (and reframing
8398 // unfortunately has side-effects sometimes, even though they're bugs).
8399 return false;
8400 }
8401 }
8402 }
8403
8404 return true;
8405}
8406
8407void nsCSSFrameConstructor::RecreateFramesForContent(
8408 nsIContent* aContent, InsertionKind aInsertionKind) {
8409 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"
, 8409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 8409; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8410
8411 // If there is no document, we don't want to recreate frames for it. (You
8412 // shouldn't generally be giving this method content without a document
8413 // anyway).
8414 // Rebuilding the frame tree can have bad effects, especially if it's the
8415 // frame tree for chrome (see bug 157322).
8416 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"
, 8416)
) {
8417 return;
8418 }
8419
8420 // TODO(emilio): We technically can find the right insertion point nowadays
8421 // using StyleChildrenIterator rather than FlattenedChildIterator. But we'd
8422 // need to tweak the setup to insert into replaced elements to filter which
8423 // anonymous roots can be allowed, and which can't.
8424 //
8425 // TODO(emilio, 2022): Is this true? If we have a replaced element we wouldn't
8426 // have generated e.g., a ::before/::after pseudo-element to begin with (which
8427 // is what this code is about, so maybe we can just remove this piece of code
8428 // altogether).
8429 if (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent)) {
8430 do {
8431 aContent = aContent->GetParent();
8432 } while (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent));
8433 return RecreateFramesForContent(aContent, InsertionKind::Async);
8434 }
8435
8436 nsIFrame* frame = aContent->GetPrimaryFrame();
8437 if (frame && frame->IsMathMLFrame()) {
8438 // Reframe the topmost MathML element to prevent exponential blowup
8439 // (see bug 397518).
8440 aContent = GetTopmostMathMLElement(aContent);
8441 frame = aContent->GetPrimaryFrame();
8442 }
8443
8444 if (frame) {
8445 nsIFrame* parent = frame->GetParent();
8446 nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
8447 // If the parent frame is a leaf then the subsequent insert will fail to
8448 // create a frame, so we need to recreate the parent content. This happens
8449 // with native anonymous content from the editor.
8450 if (parent && parent->IsLeaf() && parentContent &&
8451 parentContent != aContent) {
8452 return RecreateFramesForContent(parentContent, InsertionKind::Async);
8453 }
8454 }
8455
8456 if (frame && MaybeRecreateContainerForFrameRemoval(frame)) {
8457 return;
8458 }
8459
8460 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"
, 8460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8460; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8461
8462 // Remove the frames associated with the content object.
8463 nsIContent* nextSibling = aContent->IsRootOfNativeAnonymousSubtree()
8464 ? nullptr
8465 : aContent->GetNextSibling();
8466 bool didReconstruct =
8467 ContentRemoved(aContent, nextSibling, REMOVE_FOR_RECONSTRUCTION);
8468
8469 if (!didReconstruct) {
8470 if (aInsertionKind == InsertionKind::Async && aContent->IsElement()) {
8471 // FIXME(emilio, bug 1397239): There's nothing removing the frame state
8472 // for elements that go away before we come back to the frame
8473 // constructor.
8474 //
8475 // Also, it'd be nice to just use the `ContentRangeInserted` path for
8476 // both elements and non-elements, but we need to make lazy frame
8477 // construction to apply to all elements first.
8478 RestyleManager()->PostRestyleEvent(aContent->AsElement(), RestyleHint{0},
8479 nsChangeHint_ReconstructFrame);
8480 } else {
8481 // Now, recreate the frames associated with this content object. If
8482 // ContentRemoved triggered reconstruction, then we don't need to do this
8483 // because the frames will already have been built.
8484 ContentRangeInserted(aContent, aContent->GetNextSibling(),
8485 aInsertionKind);
8486 }
8487 }
8488}
8489
8490bool nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent) {
8491 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"
, 8491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent && aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8491; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8492
8493 nsIContent* nextSibling = aContent->IsRootOfNativeAnonymousSubtree()
8494 ? nullptr
8495 : aContent->GetNextSibling();
8496
8497 return ContentRemoved(aContent, nextSibling, REMOVE_FOR_RECONSTRUCTION);
8498}
8499
8500//////////////////////////////////////////////////////////////////////
8501
8502// Block frame construction code
8503
8504already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
8505 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8506 if (aContent) {
8507 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8508 *aContent->AsElement(), PseudoStyleType::firstLetter, nullptr,
8509 aComputedStyle);
8510 }
8511 return nullptr;
8512}
8513
8514already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
8515 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8516 if (aContent) {
8517 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8518 *aContent->AsElement(), PseudoStyleType::firstLine, nullptr,
8519 aComputedStyle);
8520 }
8521 return nullptr;
8522}
8523
8524// Predicate to see if a given content (block element) has
8525// first-letter style applied to it.
8526bool nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(
8527 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8528 return nsLayoutUtils::HasPseudoStyle(aContent, aComputedStyle,
8529 PseudoStyleType::firstLetter,
8530 mPresShell->GetPresContext());
8531}
8532
8533bool nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame) {
8534 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"
, 8534); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBlockFrame"
") (" "Need a frame" ")"); do { *((volatile int*)__null) = 8534
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8535 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"
, 8535); MOZ_PretendNoReturn(); } } while (0)
;
8536
8537 return aBlockFrame->HasAnyStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
8538}
8539
8540bool nsCSSFrameConstructor::ShouldHaveFirstLineStyle(
8541 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8542 bool hasFirstLine = nsLayoutUtils::HasPseudoStyle(
8543 aContent, aComputedStyle, PseudoStyleType::firstLine,
8544 mPresShell->GetPresContext());
8545 return hasFirstLine && !aContent->IsHTMLElement(nsGkAtoms::fieldset);
8546}
8547
8548void nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(
8549 nsIContent* aContent, ComputedStyle* aComputedStyle,
8550 bool* aHaveFirstLetterStyle, bool* aHaveFirstLineStyle) {
8551 *aHaveFirstLetterStyle = ShouldHaveFirstLetterStyle(aContent, aComputedStyle);
8552 *aHaveFirstLineStyle = ShouldHaveFirstLineStyle(aContent, aComputedStyle);
8553}
8554
8555/* static */
8556const nsCSSFrameConstructor::PseudoParentData
8557 nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
8558 // Cell
8559 {{&nsCSSFrameConstructor::ConstructTableCell,
8560 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8561 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8562 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28)},
8563 PseudoStyleType::tableCell},
8564 // Row
8565 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8566 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8567 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8568 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28)},
8569 PseudoStyleType::tableRow},
8570 // Row group
8571 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8572 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8573 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8574 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8575 PseudoStyleType::tableRowGroup},
8576 // Column group
8577 {{ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
8578 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 |
8579 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_USE_CHILD_ITEMS0x10000 |
8580 FCDATA_SKIP_ABSPOS_PUSH0x200 |
8581 // Not FCDATA_IS_WRAPPER_ANON_BOX, because we don't need to
8582 // restyle these: they have non-inheriting styles.
8583 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8584 PseudoStyleType::tableColGroup},
8585 // Table
8586 {{&nsCSSFrameConstructor::ConstructTable,
8587 FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8588 FCDATA_IS_WRAPPER_ANON_BOX0x400000},
8589 PseudoStyleType::table},
8590 // Ruby
8591 {{ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
,
8592 FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_USE_CHILD_ITEMS0x10000 |
8593 FCDATA_IS_WRAPPER_ANON_BOX0x400000 | FCDATA_SKIP_FRAMESET0x1},
8594 PseudoStyleType::ruby},
8595 // Ruby Base
8596 {{ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
8597 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8598 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8599 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28) |
8600 FCDATA_SKIP_FRAMESET0x1},
8601 PseudoStyleType::rubyBase},
8602 // Ruby Base Container
8603 {{ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
8604 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8605 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8606 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8607 FCDATA_SKIP_FRAMESET0x1},
8608 PseudoStyleType::rubyBaseContainer},
8609 // Ruby Text
8610 {{ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
8611 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8612 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8613 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28) |
8614 FCDATA_SKIP_FRAMESET0x1},
8615 PseudoStyleType::rubyText},
8616 // Ruby Text Container
8617 {{ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
8618 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8619 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8620 FCDATA_SKIP_FRAMESET0x1},
8621 PseudoStyleType::rubyTextContainer}};
8622
8623void nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
8624 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8625 nsIFrame* aParentFrame) {
8626 if (aItems.IsEmpty()) {
8627 return;
8628 }
8629
8630 if (!aParentFrame->IsFlexOrGridContainer()) {
8631 return;
8632 }
8633
8634 const bool isLegacyWebKitBox =
8635 IsFlexContainerForLegacyWebKitBox(aParentFrame);
8636 FCItemIterator iter(aItems);
8637 do {
8638 // Advance iter past children that don't want to be wrapped
8639 if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState,
8640 isLegacyWebKitBox)) {
8641 // Hit the end of the items without finding any remaining children that
8642 // need to be wrapped. We're finished!
8643 return;
8644 }
8645
8646 // If our next potentially-wrappable child is whitespace, then see if
8647 // there's anything wrappable immediately after it. If not, we just drop
8648 // the whitespace and move on. (We're not supposed to create any anonymous
8649 // flex/grid items that _only_ contain whitespace).
8650 // (BUT if this is generated content, then we don't give whitespace nodes
8651 // any special treatment, because they're probably not really whitespace --
8652 // they're just temporarily empty, waiting for their generated text.)
8653 // XXXdholbert If this node's generated text will *actually end up being
8654 // entirely whitespace*, then we technically should still skip over it, per
8655 // the CSS grid & flexbox specs. I'm not bothering with that at this point,
8656 // since it's a pretty extreme edge case.
8657 if (!aParentFrame->IsGeneratedContentFrame() &&
8658 iter.item().IsWhitespace(aState)) {
8659 FCItemIterator afterWhitespaceIter(iter);
8660 bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
8661 bool nextChildNeedsAnonItem =
8662 !hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(
8663 aState, isLegacyWebKitBox);
8664
8665 if (!nextChildNeedsAnonItem) {
8666 // There's nothing after the whitespace that we need to wrap, so we
8667 // just drop this run of whitespace.
8668 iter.DeleteItemsTo(this, afterWhitespaceIter);
8669 if (hitEnd) {
8670 // Nothing left to do -- we're finished!
8671 return;
8672 }
8673 // else, we have a next child and it does not want to be wrapped. So,
8674 // we jump back to the beginning of the loop to skip over that child
8675 // (and anything else non-wrappable after it)
8676 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"
, 8678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8678; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8677 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"
, 8678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8678; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8678 "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"
, 8678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8678; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8679 continue;
8680 }
8681 }
8682
8683 // Now |iter| points to the first child that needs to be wrapped in an
8684 // anonymous flex/grid item. Now we see how many children after it also want
8685 // to be wrapped in an anonymous flex/grid item.
8686 FCItemIterator endIter(iter); // iterator to find the end of the group
8687 endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox);
8688
8689 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"
, 8690); MOZ_PretendNoReturn(); } } while (0)
8690 "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"
, 8690); MOZ_PretendNoReturn(); } } while (0)
;
8691
8692 // Now, we create the anonymous flex or grid item to contain the children
8693 // between |iter| and |endIter|.
8694 nsIContent* parentContent = aParentFrame->GetContent();
8695 RefPtr<ComputedStyle> wrapperStyle =
8696 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
8697 PseudoStyleType::anonymousItem, aParentFrame->Style());
8698
8699 static constexpr FrameConstructionData sBlockFCData(
8700 ToCreationFunc(NS_NewBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewBlockFrame(aPs, aStyle); }
, FCDATA_SKIP_FRAMESET0x1 |
8701 FCDATA_USE_CHILD_ITEMS0x10000 |
8702 FCDATA_IS_WRAPPER_ANON_BOX0x400000);
8703
8704 // Use the content of our parent frame
8705 auto* newItem = new (this) FrameConstructionItem(
8706 &sBlockFCData, parentContent, wrapperStyle.forget(), true);
8707
8708 newItem->mIsAllInline =
8709 newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
8710 newItem->mIsBlock = !newItem->mIsAllInline;
8711
8712 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"
, 8715); 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) = 8715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8713 "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"
, 8715); 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) = 8715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8714 "(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"
, 8715); 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) = 8715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8715 "'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"
, 8715); 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) = 8715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8716
8717 // Anonymous flex and grid items induce line boundaries around their
8718 // contents.
8719 newItem->mChildItems.SetLineBoundaryAtStart(true);
8720 newItem->mChildItems.SetLineBoundaryAtEnd(true);
8721 // The parent of the items in aItems is also the parent of the items
8722 // in mChildItems
8723 newItem->mChildItems.SetParentHasNoShadowDOM(aItems.ParentHasNoShadowDOM());
8724
8725 // Eat up all items between |iter| and |endIter| and put them in our
8726 // wrapper. This advances |iter| to point to |endIter|.
8727 iter.AppendItemsToList(this, endIter, newItem->mChildItems);
8728
8729 iter.InsertItem(newItem);
8730 } while (!iter.IsDone());
8731}
8732
8733/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8734nsCSSFrameConstructor::ComputeRubyWhitespaceType(StyleDisplay aPrevDisplay,
8735 StyleDisplay aNextDisplay) {
8736 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"
, 8736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevDisplay.IsRuby() && aNextDisplay.IsRuby()"
")"); do { *((volatile int*)__null) = 8736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8737 if (aPrevDisplay == aNextDisplay &&
8738 (aPrevDisplay == StyleDisplay::RubyBase ||
8739 aPrevDisplay == StyleDisplay::RubyText)) {
8740 return eRubyInterLeafWhitespace;
8741 }
8742 if (aNextDisplay == StyleDisplay::RubyText ||
8743 aNextDisplay == StyleDisplay::RubyTextContainer) {
8744 return eRubyInterLevelWhitespace;
8745 }
8746 return eRubyInterSegmentWhitespace;
8747}
8748
8749/**
8750 * This function checks the content from |aStartIter| to |aEndIter|,
8751 * determines whether it contains only whitespace, and if yes,
8752 * interprets the type of whitespace. This method does not change
8753 * any of the iters.
8754 */
8755/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8756nsCSSFrameConstructor::InterpretRubyWhitespace(nsFrameConstructorState& aState,
8757 const FCItemIterator& aStartIter,
8758 const FCItemIterator& aEndIter) {
8759 if (!aStartIter.item().IsWhitespace(aState)) {
8760 return eRubyNotWhitespace;
8761 }
8762
8763 FCItemIterator spaceEndIter(aStartIter);
8764 spaceEndIter.SkipWhitespace(aState);
8765 if (spaceEndIter != aEndIter) {
8766 return eRubyNotWhitespace;
8767 }
8768
8769 // Any leading or trailing whitespace in non-pseudo ruby box
8770 // should have been trimmed, hence there should not be any
8771 // whitespace at the start or the end.
8772 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"
, 8772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aStartIter.AtStart() && !aEndIter.IsDone()"
")"); do { *((volatile int*)__null) = 8772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8773 FCItemIterator prevIter(aStartIter);
8774 prevIter.Prev();
8775 return ComputeRubyWhitespaceType(
8776 prevIter.item().mComputedStyle->StyleDisplay()->mDisplay,
8777 aEndIter.item().mComputedStyle->StyleDisplay()->mDisplay);
8778}
8779
8780/**
8781 * This function eats up consecutive items which do not want the current
8782 * parent into either a ruby base box or a ruby text box. When it
8783 * returns, |aIter| points to the first item it doesn't wrap.
8784 */
8785void nsCSSFrameConstructor::WrapItemsInPseudoRubyLeafBox(
8786 FCItemIterator& aIter, ComputedStyle* aParentStyle,
8787 nsIContent* aParentContent) {
8788 StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
8789 ParentType parentType, wrapperType;
8790 if (parentDisplay == StyleDisplay::RubyTextContainer) {
8791 parentType = eTypeRubyTextContainer;
8792 wrapperType = eTypeRubyText;
8793 } else {
8794 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"
, 8794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentDisplay == StyleDisplay::RubyBaseContainer"
")"); do { *((volatile int*)__null) = 8794; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8795 parentType = eTypeRubyBaseContainer;
8796 wrapperType = eTypeRubyBase;
8797 }
8798
8799 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"
, 8800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8800 "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"
, 8800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8801
8802 FCItemIterator endIter(aIter);
8803 endIter.SkipItemsNotWantingParentType(parentType);
8804
8805 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8806 endIter);
8807}
8808
8809/**
8810 * This function eats up consecutive items into a ruby level container.
8811 * It may create zero or one level container. When it returns, |aIter|
8812 * points to the first item it doesn't wrap.
8813 */
8814void nsCSSFrameConstructor::WrapItemsInPseudoRubyLevelContainer(
8815 nsFrameConstructorState& aState, FCItemIterator& aIter,
8816 ComputedStyle* aParentStyle, nsIContent* aParentContent) {
8817 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"
, 8818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8818; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8818 "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"
, 8818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8818; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8819
8820 FrameConstructionItem& firstItem = aIter.item();
8821 ParentType wrapperType = firstItem.DesiredParentType();
8822 if (wrapperType != eTypeRubyTextContainer) {
8823 // If the first item is not ruby text,
8824 // it should be in a base container.
8825 wrapperType = eTypeRubyBaseContainer;
8826 }
8827
8828 FCItemIterator endIter(aIter);
8829 do {
8830 if (endIter.SkipItemsWantingParentType(wrapperType) ||
8831 // If the skipping above stops at some item which wants a
8832 // different ruby parent, then we have finished.
8833 IsRubyParentType(endIter.item().DesiredParentType())) {
8834 // No more items need to be wrapped in this level container.
8835 break;
8836 }
8837
8838 FCItemIterator contentEndIter(endIter);
8839 contentEndIter.SkipItemsNotWantingRubyParent();
8840 // endIter must be on something doesn't want a ruby parent.
8841 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"
, 8841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentEndIter != endIter"
")"); do { *((volatile int*)__null) = 8841; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8842
8843 // InterpretRubyWhitespace depends on the fact that any leading or
8844 // trailing whitespace described in the spec have been trimmed at
8845 // this point. With this precondition, it is safe not to check
8846 // whether contentEndIter has been done.
8847 RubyWhitespaceType whitespaceType =
8848 InterpretRubyWhitespace(aState, endIter, contentEndIter);
8849 if (whitespaceType == eRubyInterLevelWhitespace) {
8850 // Remove inter-level whitespace.
8851 bool atStart = (aIter == endIter);
8852 endIter.DeleteItemsTo(this, contentEndIter);
8853 if (atStart) {
8854 aIter = endIter;
8855 }
8856 } else if (whitespaceType == eRubyInterSegmentWhitespace) {
8857 // If this level container starts with inter-segment whitespaces,
8858 // wrap them. Break at contentEndIter. Otherwise, leave it here.
8859 // Break at endIter. They will be wrapped when we are here again.
8860 if (aIter == endIter) {
8861 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"
, 8862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8862 "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"
, 8862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8863 endIter = contentEndIter;
8864 }
8865 break;
8866 } else if (wrapperType == eTypeRubyTextContainer &&
8867 whitespaceType != eRubyInterLeafWhitespace) {
8868 // Misparented inline content that's not inter-annotation
8869 // whitespace doesn't belong in a pseudo ruby text container.
8870 // Break at endIter.
8871 break;
8872 } else {
8873 endIter = contentEndIter;
8874 }
8875 } while (!endIter.IsDone());
8876
8877 // It is possible that everything our parent wants us to wrap is
8878 // simply an inter-level whitespace, which has been trimmed, or
8879 // an inter-segment whitespace, which will be wrapped later.
8880 // In those cases, don't create anything.
8881 if (aIter != endIter) {
8882 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8883 endIter);
8884 }
8885}
8886
8887/**
8888 * This function trims leading and trailing whitespaces
8889 * in the given item list.
8890 */
8891void nsCSSFrameConstructor::TrimLeadingAndTrailingWhitespaces(
8892 nsFrameConstructorState& aState, FrameConstructionItemList& aItems) {
8893 FCItemIterator iter(aItems);
8894 if (!iter.IsDone() && iter.item().IsWhitespace(aState)) {
8895 FCItemIterator spaceEndIter(iter);
8896 spaceEndIter.SkipWhitespace(aState);
8897 iter.DeleteItemsTo(this, spaceEndIter);
8898 }
8899
8900 iter.SetToEnd();
8901 if (!iter.AtStart()) {
8902 FCItemIterator spaceEndIter(iter);
8903 do {
8904 iter.Prev();
8905 if (iter.AtStart()) {
8906 // It's fine to not check the first item, because we
8907 // should have trimmed leading whitespaces above.
8908 break;
8909 }
8910 } while (iter.item().IsWhitespace(aState));
8911 iter.Next();
8912 if (iter != spaceEndIter) {
8913 iter.DeleteItemsTo(this, spaceEndIter);
8914 }
8915 }
8916}
8917
8918/**
8919 * This function walks through the child list (aItems) and creates
8920 * needed pseudo ruby boxes to wrap misparented children.
8921 */
8922void nsCSSFrameConstructor::CreateNeededPseudoInternalRubyBoxes(
8923 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8924 nsIFrame* aParentFrame) {
8925 const ParentType ourParentType = GetParentType(aParentFrame);
8926 if (!IsRubyParentType(ourParentType) ||
8927 aItems.AllWantParentType(ourParentType)) {
8928 return;
8929 }
8930
8931 if (!IsRubyPseudo(aParentFrame) ||
8932 ourParentType == eTypeRuby /* for 'display:block ruby' */) {
8933 // Normally, ruby pseudo frames start from and end at some elements,
8934 // which means they don't have leading and trailing whitespaces at
8935 // all. But there are two cases where they do actually have leading
8936 // or trailing whitespaces:
8937 // 1. It is an inter-segment whitespace which in an individual ruby
8938 // base container.
8939 // 2. The pseudo frame starts from or ends at consecutive inline
8940 // content, which is not pure whitespace, but includes some.
8941 // In either case, the whitespaces are not the leading or trailing
8942 // whitespaces defined in the spec, and thus should not be trimmed.
8943 TrimLeadingAndTrailingWhitespaces(aState, aItems);
8944 }
8945
8946 FCItemIterator iter(aItems);
8947 nsIContent* parentContent = aParentFrame->GetContent();
8948 ComputedStyle* parentStyle = aParentFrame->Style();
8949 while (!iter.IsDone()) {
8950 if (!iter.SkipItemsWantingParentType(ourParentType)) {
8951 if (ourParentType == eTypeRuby) {
8952 WrapItemsInPseudoRubyLevelContainer(aState, iter, parentStyle,
8953 parentContent);
8954 } else {
8955 WrapItemsInPseudoRubyLeafBox(iter, parentStyle, parentContent);
8956 }
8957 }
8958 }
8959}
8960
8961/*
8962 * This function works as follows: we walk through the child list (aItems) and
8963 * find items that cannot have aParentFrame as their parent. We wrap
8964 * continuous runs of such items into a FrameConstructionItem for a frame that
8965 * gets them closer to their desired parents. For example, a run of non-row
8966 * children of a row-group will get wrapped in a row. When we later construct
8967 * the frame for this wrapper (in this case for the row), it'll be the correct
8968 * parent for the cells in the set of items we wrapped or we'll wrap cells
8969 * around everything else. At the end of this method, aItems is guaranteed to
8970 * contain only items for frames that can be direct kids of aParentFrame.
8971 */
8972void nsCSSFrameConstructor::CreateNeededPseudoContainers(
8973 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8974 nsIFrame* aParentFrame) {
8975 ParentType ourParentType = GetParentType(aParentFrame);
8976 if (IsRubyParentType(ourParentType) ||
8977 aItems.AllWantParentType(ourParentType)) {
8978 // Nothing to do here
8979 return;
8980 }
8981
8982 FCItemIterator iter(aItems);
8983 do {
8984 if (iter.SkipItemsWantingParentType(ourParentType)) {
8985 // Nothing else to do here; we're finished
8986 return;
8987 }
8988
8989 // Now we're pointing to the first child that wants a different parent
8990 // type.
8991
8992 // Now try to figure out what kids we can group together. We can generally
8993 // group everything that has a different desired parent type from us. Two
8994 // exceptions to this:
8995 // 1) If our parent type is table, we can't group columns with anything
8996 // else other than whitespace.
8997 // 2) Whitespace that lies between two things we can group which both want
8998 // a non-block parent should be dropped, even if we can't group them
8999 // with each other and even if the whitespace wants a parent of
9000 // ourParentType. Ends of the list count as things that don't want a
9001 // block parent (so that for example we'll drop a whitespace-only list).
9002
9003 FCItemIterator endIter(iter); /* iterator to find the end of the group */
9004 ParentType groupingParentType = endIter.item().DesiredParentType();
9005 if (aItems.AllWantParentType(groupingParentType) &&
9006 groupingParentType != eTypeBlock) {
9007 // Just group them all and be done with it. We need the check for
9008 // eTypeBlock here to catch the "all the items are whitespace" case
9009 // described above.
9010 endIter.SetToEnd();
9011 } else {
9012 // Locate the end of the group.
9013
9014 // Keep track of the type the previous item wanted, in case we have to
9015 // deal with whitespace. Start it off with ourParentType, since that's
9016 // the last thing |iter| would have skipped over.
9017 ParentType prevParentType = ourParentType;
9018 do {
9019 // Walk an iterator past any whitespace that we might be able to drop
9020 // from the list
9021 FCItemIterator spaceEndIter(endIter);
9022 if (prevParentType != eTypeBlock &&
9023 !aParentFrame->IsGeneratedContentFrame() &&
9024 spaceEndIter.item().IsWhitespace(aState)) {
9025 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
9026
9027 // We drop the whitespace in the following cases:
9028 // 1) If these are not trailing spaces and the next item wants a table
9029 // or table-part parent
9030 // 2) If these are trailing spaces and aParentFrame is a
9031 // tabular container according to rule 1.3 of CSS 2.1 Sec 17.2.1.
9032 // (Being a tabular container pretty much means ourParentType is
9033 // not eTypeBlock besides the eTypeColGroup case, which won't
9034 // reach here.)
9035 if ((!trailingSpaces &&
9036 IsTableParentType(spaceEndIter.item().DesiredParentType())) ||
9037 (trailingSpaces && ourParentType != eTypeBlock)) {
9038 bool updateStart = (iter == endIter);
9039 endIter.DeleteItemsTo(this, spaceEndIter);
9040 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"
, 9041); MOZ_PretendNoReturn(); } } while (0)
9041 "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"
, 9041); MOZ_PretendNoReturn(); } } while (0)
;
9042
9043 if (updateStart) {
9044 iter = endIter;
9045 }
9046
9047 if (trailingSpaces) {
9048 break; /* Found group end */
9049 }
9050
9051 if (updateStart) {
9052 // Update groupingParentType, since it might have been eTypeBlock
9053 // just because of the whitespace.
9054 groupingParentType = iter.item().DesiredParentType();
9055 }
9056 }
9057 }
9058
9059 // Now endIter points to a non-whitespace item or a non-droppable
9060 // whitespace item. In the latter case, if this is the end of the group
9061 // we'll traverse this whitespace again. But it'll all just be quick
9062 // DesiredParentType() checks which will match ourParentType (that's
9063 // what it means that this is the group end), so it's OK.
9064 // However, when we are grouping a ruby parent, and endIter points to
9065 // a non-droppable whitespace, if the next non-whitespace item also
9066 // wants a ruby parent, the whitespace should also be included into
9067 // the current ruby container.
9068 prevParentType = endIter.item().DesiredParentType();
9069 if (prevParentType == ourParentType &&
9070 (endIter == spaceEndIter || spaceEndIter.IsDone() ||
9071 !IsRubyParentType(groupingParentType) ||
9072 !IsRubyParentType(spaceEndIter.item().DesiredParentType()))) {
9073 // End the group at endIter.
9074 break;
9075 }
9076
9077 if (ourParentType == eTypeTable &&
9078 (prevParentType == eTypeColGroup) !=
9079 (groupingParentType == eTypeColGroup)) {
9080 // Either we started with columns and now found something else, or
9081 // vice versa. In any case, end the grouping.
9082 break;
9083 }
9084
9085 // If we have some whitespace that we were not able to drop and there is
9086 // an item after the whitespace that is already properly parented, then
9087 // make sure to include the spaces in our group but stop the group after
9088 // that.
9089 if (spaceEndIter != endIter && !spaceEndIter.IsDone() &&
9090 ourParentType == spaceEndIter.item().DesiredParentType()) {
9091 endIter = spaceEndIter;
9092 break;
9093 }
9094
9095 // Include the whitespace we didn't drop (if any) in the group.
9096 endIter = spaceEndIter;
9097 prevParentType = endIter.item().DesiredParentType();
9098
9099 endIter.Next();
9100 } while (!endIter.IsDone());
9101 }
9102
9103 if (iter == endIter) {
9104 // Nothing to wrap here; just skipped some whitespace
9105 continue;
9106 }
9107
9108 // Now group together all the items between iter and endIter. The right
9109 // parent type to use depends on ourParentType.
9110 ParentType wrapperType;
9111 switch (ourParentType) {
9112 case eTypeRow:
9113 // The parent type for a cell is eTypeBlock, since that's what a cell
9114 // looks like to its kids.
9115 wrapperType = eTypeBlock;
9116 break;
9117 case eTypeRowGroup:
9118 wrapperType = eTypeRow;
9119 break;
9120 case eTypeTable:
9121 // Either colgroup or rowgroup, depending on what we're grouping.
9122 wrapperType =
9123 groupingParentType == eTypeColGroup ? eTypeColGroup : eTypeRowGroup;
9124 break;
9125 case eTypeColGroup:
9126 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"
, 9126); AnnotateMozCrashReason("MOZ_CRASH(" "Colgroups should be suppresing non-col child items"
")"); do { *((volatile int*)__null) = 9126; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9127 default:
9128 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"
, 9128); MOZ_PretendNoReturn(); } } while (0)
;
9129 if (IsRubyParentType(groupingParentType)) {
9130 wrapperType = eTypeRuby;
9131 } else {
9132 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"
, 9133); MOZ_PretendNoReturn(); } } while (0)
9133 "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"
, 9133); MOZ_PretendNoReturn(); } } while (0)
;
9134 wrapperType = eTypeTable;
9135 }
9136 }
9137
9138 ComputedStyle* parentStyle = aParentFrame->Style();
9139 WrapItemsInPseudoParent(aParentFrame->GetContent(), parentStyle,
9140 wrapperType, iter, endIter);
9141
9142 // Now |iter| points to the item that was the first one we didn't wrap;
9143 // loop and see whether we need to skip it or wrap it in something
9144 // different.
9145 } while (!iter.IsDone());
9146}
9147
9148/**
9149 * This method wraps frame construction item from |aIter| to
9150 * |aEndIter|. After it returns, aIter points to the first item
9151 * after the wrapper.
9152 */
9153void nsCSSFrameConstructor::WrapItemsInPseudoParent(
9154 nsIContent* aParentContent, ComputedStyle* aParentStyle,
9155 ParentType aWrapperType, FCItemIterator& aIter,
9156 const FCItemIterator& aEndIter) {
9157 const PseudoParentData& pseudoData = sPseudoParentData[aWrapperType];
9158 PseudoStyleType pseudoType = pseudoData.mPseudoType;
9159 auto& parentDisplay = *aParentStyle->StyleDisplay();
9160 auto parentDisplayInside = parentDisplay.DisplayInside();
9161
9162 // XXXmats should we use IsInlineInsideStyle() here instead? seems odd to
9163 // exclude RubyBaseContainer/RubyTextContainer...
9164 if (pseudoType == PseudoStyleType::table &&
9165 (parentDisplay.IsInlineFlow() ||
9166 parentDisplayInside == StyleDisplayInside::RubyBase ||
9167 parentDisplayInside == StyleDisplayInside::RubyText)) {
9168 pseudoType = PseudoStyleType::inlineTable;
9169 }
9170
9171 RefPtr<ComputedStyle> wrapperStyle;
9172 if (pseudoData.mFCData.mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000) {
9173 wrapperStyle = mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9174 pseudoType, aParentStyle);
9175 } else {
9176 wrapperStyle =
9177 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
9178 pseudoType);
9179 }
9180
9181 // Use the content of our parent frame
9182 auto* newItem = new (this) FrameConstructionItem(
9183 &pseudoData.mFCData, aParentContent, wrapperStyle.forget(), true);
9184
9185 const nsStyleDisplay* disp = newItem->mComputedStyle->StyleDisplay();
9186 // Here we're cheating a tad... technically, table-internal items should be
9187 // inline if aParentFrame is inline, but they'll get wrapped in an
9188 // inline-table in the end, so it'll all work out. In any case, arguably
9189 // we don't need to maintain this state at this point... but it's better
9190 // to, I guess.
9191 newItem->mIsAllInline = disp->IsInlineOutsideStyle();
9192
9193 bool isRuby = disp->IsRubyDisplayType();
9194 if (!isRuby) {
9195 // Table pseudo frames always induce line boundaries around their
9196 // contents.
9197 newItem->mChildItems.SetLineBoundaryAtStart(true);
9198 newItem->mChildItems.SetLineBoundaryAtEnd(true);
9199 }
9200 // The parent of the items in aItems is also the parent of the items
9201 // in mChildItems
9202 newItem->mChildItems.SetParentHasNoShadowDOM(
9203 aIter.List()->ParentHasNoShadowDOM());
9204
9205 // Eat up all items between |aIter| and |aEndIter| and put them in our
9206 // wrapper Advances |aIter| to point to |aEndIter|.
9207 aIter.AppendItemsToList(this, aEndIter, newItem->mChildItems);
9208
9209 aIter.InsertItem(newItem);
9210}
9211
9212void nsCSSFrameConstructor::CreateNeededPseudoSiblings(
9213 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9214 nsIFrame* aParentFrame) {
9215 if (aItems.IsEmpty() || GetParentType(aParentFrame) != eTypeRuby) {
9216 return;
9217 }
9218
9219 FCItemIterator iter(aItems);
9220 StyleDisplay firstDisplay =
9221 iter.item().mComputedStyle->StyleDisplay()->mDisplay;
9222 if (firstDisplay == StyleDisplay::RubyBaseContainer) {
9223 return;
9224 }
9225 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"
, 9226); MOZ_PretendNoReturn(); } } while (0)
9226 "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"
, 9226); MOZ_PretendNoReturn(); } } while (0)
;
9227
9228 const PseudoParentData& pseudoData =
9229 sPseudoParentData[eTypeRubyBaseContainer];
9230 RefPtr<ComputedStyle> pseudoStyle =
9231 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9232 pseudoData.mPseudoType, aParentFrame->Style());
9233 FrameConstructionItem* newItem = new (this) FrameConstructionItem(
9234 &pseudoData.mFCData,
9235 // Use the content of the parent frame
9236 aParentFrame->GetContent(), pseudoStyle.forget(), true);
9237 newItem->mIsAllInline = true;
9238 newItem->mChildItems.SetParentHasNoShadowDOM(true);
9239 iter.InsertItem(newItem);
9240}
9241
9242#ifdef DEBUG1
9243/**
9244 * Returns true iff aFrame should be wrapped in an anonymous flex/grid item,
9245 * rather than being a direct child of aContainerFrame.
9246 *
9247 * NOTE: aContainerFrame must be a flex or grid container - this function is
9248 * purely for sanity-checking the children of these container types.
9249 * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
9250 * logic (which operates a bit earlier, on FCData instead of frames).
9251 */
9252static bool FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
9253 const nsIFrame* aFrame) {
9254 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"
, 9254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContainerFrame->IsFlexOrGridContainer()"
")"); do { *((volatile int*)__null) = 9254; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9255
9256 // Any line-participant frames (e.g. text) definitely want to be wrapped in
9257 // an anonymous flex/grid item.
9258 if (aFrame->IsLineParticipant()) {
9259 return true;
9260 }
9261
9262 // If the container is a -webkit-{inline-}box container, then placeholders
9263 // also need to be wrapped, for compatibility.
9264 if (IsFlexContainerForLegacyWebKitBox(aContainerFrame) &&
9265 aFrame->IsPlaceholderFrame()) {
9266 return true;
9267 }
9268
9269 return false;
9270}
9271#endif
9272
9273static void VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
9274 const nsFrameList& aChildren) {
9275#ifdef DEBUG1
9276 if (!aParentFrame->IsFlexOrGridContainer()) {
9277 return;
9278 }
9279
9280 bool prevChildWasAnonItem = false;
9281 for (const nsIFrame* child : aChildren) {
9282 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"
, 9283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9283 "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"
, 9283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9284 if (IsAnonymousItem(child)) {
9285 AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
9286 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"
, 9286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prevChildWasAnonItem"
") (" "two anon items in a row" ")"); do { *((volatile int*)
__null) = 9286; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9287 nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
9288 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"
, 9288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstWrappedChild"
") (" "anonymous item shouldn't be empty" ")"); do { *((volatile
int*)__null) = 9288; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9289 prevChildWasAnonItem = true;
9290 } else {
9291 prevChildWasAnonItem = false;
9292 }
9293 }
9294#endif
9295}
9296
9297static bool FrameHasOnlyPlaceholderPrevSiblings(const nsIFrame* aFrame) {
9298 // Check for prev siblings, ignoring placeholder frames.
9299 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"
, 9299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9299; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9300 const nsIFrame* prevSibling = aFrame;
9301 do {
9302 prevSibling = prevSibling->GetPrevSibling();
9303 } while (prevSibling && prevSibling->IsPlaceholderFrame());
9304 return !prevSibling;
9305}
9306
9307static bool FrameHasOnlyPlaceholderNextSiblings(const nsIFrame* aFrame) {
9308 // Check for next siblings, ignoring placeholder frames.
9309 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"
, 9309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9309; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9310 const nsIFrame* nextSibling = aFrame;
9311 do {
9312 nextSibling = nextSibling->GetNextSibling();
9313 } while (nextSibling && nextSibling->IsPlaceholderFrame());
9314 return !nextSibling;
9315}
9316
9317static void SetPageValues(nsIFrame* const aFrame,
9318 const nsAtom* const aAutoValue,
9319 const nsAtom* const aStartValue,
9320 const nsAtom* const aEndValue) {
9321 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"
, 9321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAutoValue"
") (" "Auto page value should never be null" ")"); do { *((volatile
int*)__null) = 9321; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9322 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"
, 9322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartValue || aEndValue"
") (" "Should not have called with no values" ")"); do { *((
volatile int*)__null) = 9322; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9323 nsIFrame::PageValues* pageValues =
9324 aFrame->GetProperty(nsIFrame::PageValuesProperty());
9325
9326 if (aStartValue) {
9327 if (aStartValue == aAutoValue) {
9328 // If the page value struct already exists, set the start value to null
9329 // to indicate the auto value.
9330 if (pageValues) {
9331 pageValues->mStartPageValue = nullptr;
9332 }
9333 } else {
9334 // The start value is not auto, so we need to store it, creating the
9335 // page values struct if it does not already exist.
9336 if (!pageValues) {
9337 pageValues = new nsIFrame::PageValues();
9338 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9339 }
9340 pageValues->mStartPageValue = aStartValue;
9341 }
9342 }
9343 if (aEndValue) {
9344 if (aEndValue == aAutoValue) {
9345 // If the page value struct already exists, set the end value to null
9346 // to indicate the auto value.
9347 if (pageValues) {
9348 pageValues->mEndPageValue = nullptr;
9349 }
9350 } else {
9351 // The end value is not auto, so we need to store it, creating the
9352 // page values struct if it does not already exist.
9353 if (!pageValues) {
9354 pageValues = new nsIFrame::PageValues();
9355 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9356 }
9357 pageValues->mEndPageValue = aEndValue;
9358 }
9359 }
9360}
9361
9362inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
9363 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9364 nsContainerFrame* aParentFrame, bool aParentIsWrapperAnonBox,
9365 nsFrameList& aFrameList) {
9366#ifdef DEBUG1
9367 if (aParentFrame->StyleContent()->mContent.IsNone() &&
9368 StaticPrefs::layout_css_element_content_none_enabled()) {
9369 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9370 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"
, 9371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9371 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"
, 9371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9372 }
9373 }
9374
9375 // The assertion condition should match the logic in
9376 // MaybePushFloatContainingBlock().
9377 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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9378 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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9379 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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9380 "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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9381 "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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9382 "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"
, 9382); 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) = 9382
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9383 aState.mFloatCBCandidate = nullptr;
9384#endif
9385
9386 // Ensure aParentIsWrapperAnonBox is correct. We _could_ compute it directly,
9387 // but it would be a bit slow, which is why we pass it from callers, who have
9388 // that information offhand in many cases.
9389 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"
, 9389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox"
")"); do { *((volatile int*)__null) = 9389; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9390
9391 // Note: we explicitly exclude TableColGroupFrame because it doesn't
9392 // have the FCDATA_IS_WRAPPER_ANON_BOX on pseudos so aParentIsWrapperAnonBox
9393 // is false for such pseudos (see sPseudoParentData below).
9394 if (!aParentIsWrapperAnonBox && aState.mHasRenderedLegend &&
9395 aParentFrame->GetContent()->IsHTMLElement(nsGkAtoms::fieldset) &&
9396 !aParentFrame->IsTableColGroupFrame()) {
9397 DebugOnly<bool> found = false;
9398 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9399 if (iter.item().mIsRenderedLegend) {
9400 // This makes the rendered legend the first frame in the fieldset child
9401 // list which makes keyboard traversal follow the visual order.
9402 nsFieldSetFrame* fieldSetFrame = GetFieldSetFrameFor(aParentFrame);
9403 nsFrameList renderedLegend;
9404 ConstructFramesFromItem(aState, iter, fieldSetFrame, renderedLegend);
9405 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"
, 9406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9406 "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"
, 9406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9407 fieldSetFrame->InsertFrames(FrameChildListID::Principal, nullptr,
9408 nullptr, std::move(renderedLegend));
9409 FCItemIterator next = iter;
9410 next.Next();
9411 iter.DeleteItemsTo(this, next);
9412 found = true;
9413 break;
9414 }
9415 }
9416 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"
, 9416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ") ("
"should have found our rendered legend" ")"); do { *((volatile
int*)__null) = 9416; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9417 }
9418
9419 CreateNeededPseudoContainers(aState, aItems, aParentFrame);
9420 CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
9421 CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
9422 CreateNeededPseudoSiblings(aState, aItems, aParentFrame);
9423
9424 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9425 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"
, 9427); 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) = 9427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9426 "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"
, 9427); 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) = 9427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9427 "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"
, 9427); 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) = 9427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9428 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"
, 9429); MOZ_PretendNoReturn(); } } while (0)
9429 "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"
, 9429); MOZ_PretendNoReturn(); } } while (0)
;
9430 ConstructFramesFromItem(aState, iter, aParentFrame, aFrameList);
9431 }
9432
9433 VerifyGridFlexContainerChildren(aParentFrame, aFrameList);
9434
9435 // Calculate and propagate page-name values for each frame in the frame list.
9436 // We do not want to compute and propagate page-name values from frames that
9437 // are children of any subclasses of block frames, but not actually a block
9438 // frame. The page-name property does not apply to frames which cannot create
9439 // class A breakpoints (currently no subclass of BlockFrame can). Because the
9440 // property does not apply, those children also cannot propagate page-name
9441 // values.
9442 // This assumption helps avoid unnecessarily handling page-names for frames
9443 // such as form controls, which also avoids bug 1819468.
9444 if (aState.mPresContext->IsPaginated() && aParentFrame->IsBlockFrame()) {
9445 // Set the start/end page values while iterating the frame list, to walk
9446 // up the frame tree only once after iterating the frame list.
9447 // This also avoids extra property lookups on these frames.
9448 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"
, 9450); 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) = 9450; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9449 "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"
, 9450); 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) = 9450; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9450 "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"
, 9450); 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) = 9450; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9451 // Even though we store null for page values that equal the "auto" resolved
9452 // value on frames, we always want startPageValue/endPageValue to be the
9453 // actual atoms reflecting the start/end values. This is because when we
9454 // propagate the values up the frame tree, we will need to compare them to
9455 // the auto value for each ancestor. This value might be different than the
9456 // auto value for this frame.
9457 const nsAtom* startPageValue = nullptr;
9458 const nsAtom* endPageValue = nullptr;
9459 for (nsIFrame* f : aFrameList) {
9460 if (f->IsPlaceholderFrame()) {
9461 continue;
9462 }
9463 // Resolve auto against the parent frame's used page name, which has been
9464 // determined and set on aState.mAutoPageNameValue. If this item is not
9465 // block-level then we use the value that auto resolves to.
9466 //
9467 // This is to achieve the propagation behavior described in the spec:
9468 //
9469 // "A start page value and end page value is determined for each box as
9470 // the value (if any) propagated from its first or last child box
9471 // (respectively), else the used value on the box itself."
9472 //
9473 // "A child propagates its own start or end page value if and only if the
9474 // page property applies to it."
9475 //
9476 // The page property only applies to "boxes that create class A break
9477 // points". When taken together, this means that non block-level children
9478 // do not propagate start/end page values, and instead we use "the used
9479 // value on the box itself", the "box itself" being aParentFrame. This
9480 // value has been determined and saved as aState.mAutoPageNameValue
9481 //
9482 // https://www.w3.org/TR/css-page-3/#using-named-pages
9483 // https://www.w3.org/TR/css-break-3/#btw-blocks
9484 const StylePageName& pageName = f->StylePage()->mPage;
9485 const nsAtom* const pageNameAtom =
9486 (pageName.IsPageName() && f->IsBlockOutside())
9487 ? pageName.AsPageName().AsAtom()
9488 : aState.mAutoPageNameValue;
9489 nsIFrame::PageValues* pageValues =
9490 f->GetProperty(nsIFrame::PageValuesProperty());
9491 // If this frame has any children, it will already have had its page
9492 // values set at this point. However, if no page values have been set,
9493 // we must ensure that the appropriate PageValuesProperty value has been
9494 // set.
9495 // If the page name is equal to the auto value, then PageValuesProperty
9496 // should remain null to indicate that the start/end values are both
9497 // equal to the auto value.
9498 if (pageNameAtom != aState.mAutoPageNameValue && !pageValues) {
9499 pageValues = new nsIFrame::PageValues{pageNameAtom, pageNameAtom};
9500 f->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9501 }
9502 // We don't want to use GetStartPageValue() or GetEndPageValue(), as each
9503 // requires a property lookup which we can avoid here.
9504 if (!startPageValue) {
9505 startPageValue = (pageValues && pageValues->mStartPageValue)
9506 ? pageValues->mStartPageValue.get()
9507 : aState.mAutoPageNameValue;
9508 }
9509 endPageValue = (pageValues && pageValues->mEndPageValue)
9510 ? pageValues->mEndPageValue.get()
9511 : aState.mAutoPageNameValue;
9512 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"
, 9513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9513; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9513 "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"
, 9513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9513; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9514 }
9515 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"
, 9516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9516; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9516 "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"
, 9516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9516; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9517 if (startPageValue) {
9518 // Walk up the frame tree from our parent frame, propagating start and
9519 // end page values.
9520 // As we go, if we find that, for a frame, we are not contributing one of
9521 // the start/end page values, then our subtree will not contribute this
9522 // value from that frame onward. startPageValue/endPageValue are set to
9523 // null to indicate this.
9524 // Stop iterating when we are not contributing either start or end
9525 // values, when we hit the root frame (no parent), or when we find a
9526 // frame that is not a block frame.
9527 for (nsContainerFrame* ancestorFrame = aParentFrame;
9528 (startPageValue || endPageValue) && ancestorFrame &&
9529 ancestorFrame->IsBlockFrame();
9530 ancestorFrame = ancestorFrame->GetParent()) {
9531 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"
, 9532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9532; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9532 "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"
, 9532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9532; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9533 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"
, 9535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9535; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9534 "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"
, 9535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9535; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9535 "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"
, 9535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9535; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9536 {
9537 // Get what the auto value is, based on this frame's parent.
9538 // For the root frame, `auto` resolves to the empty atom.
9539 const nsContainerFrame* const parent = ancestorFrame->GetParent();
9540 const nsAtom* const parentAuto = MOZ_LIKELY(parent)(__builtin_expect(!!(parent), 1))
9541 ? parent->GetAutoPageValue()
9542 : nsGkAtoms::_empty;
9543 SetPageValues(ancestorFrame, parentAuto, startPageValue,
9544 endPageValue);
9545 }
9546 // Once we stop contributing start/end values, we know there is a
9547 // sibling subtree that contributed that value to our shared parent
9548 // instead of our starting frame's subtree. This means once
9549 // startPageValue/endPageValue becomes null, indicating that we are no
9550 // longer contributing that page value, it should stay null and we no
9551 // longer need to check for siblings in that direction.
9552 if (startPageValue &&
9553 !FrameHasOnlyPlaceholderPrevSiblings(ancestorFrame)) {
9554 startPageValue = nullptr;
9555 }
9556 if (endPageValue &&
9557 !FrameHasOnlyPlaceholderNextSiblings(ancestorFrame)) {
9558 endPageValue = nullptr;
9559 }
9560 }
9561 }
9562 }
9563
9564 if (aParentIsWrapperAnonBox) {
9565 for (nsIFrame* f : aFrameList) {
9566 f->SetParentIsWrapperAnonBox();
9567 }
9568 }
9569}
9570
9571void nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
9572 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
9573 const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
9574 FrameConstructionItemList& aItemsToConstruct,
9575 const AutoFrameConstructionPageName&) {
9576 for (const auto& info : aAnonymousItems) {
9577 nsIContent* content = info.mContent;
9578 // Gecko-styled nodes should have no pending restyle flags.
9579 // Assert some things about this content
9580 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"
, 9582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9582; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9581 (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"
, 9582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9582; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9582 "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"
, 9582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9582; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9583 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"
, 9583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->GetPrimaryFrame()"
") (" "Should have no existing frame" ")"); do { *((volatile
int*)__null) = 9583; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9584 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"
, 9585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9585 "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"
, 9585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9586
9587 // Make sure we eagerly performed the servo cascade when the anonymous
9588 // nodes were created.
9589 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"
, 9589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsElement() || content->AsElement()->HasServoData()"
")"); do { *((volatile int*)__null) = 9589; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9590
9591 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(content);
9592
9593 AddFrameConstructionItemsInternal(aState, content, aFrame, true,
9594 computedStyle, {ItemFlag::AllowPageBreak},
9595 aItemsToConstruct);
9596 }
9597}
9598
9599void nsCSSFrameConstructor::ProcessChildren(
9600 nsFrameConstructorState& aState, nsIContent* aContent,
9601 ComputedStyle* aComputedStyle, nsContainerFrame* aFrame,
9602 const bool aCanHaveGeneratedContent, nsFrameList& aFrameList,
9603 const bool aAllowBlockStyles, nsIFrame* aPossiblyLeafFrame) {
9604 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"
, 9604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have parent frame here" ")"); do { *((volatile int*)__null
) = 9604; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9605 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"
, 9607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9607; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9606 "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"
, 9607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9607; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9607 "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"
, 9607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9607; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9608
9609 const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH1026;
9610 static_assert(kMaxDepth <= UINT16_MAX(65535), "mCurrentDepth type is too narrow");
9611 AutoRestore<uint16_t> savedDepth(mCurrentDepth);
9612 if (mCurrentDepth != UINT16_MAX(65535)) {
9613 ++mCurrentDepth;
9614 }
9615
9616 if (!aPossiblyLeafFrame) {
9617 aPossiblyLeafFrame = aFrame;
9618 }
9619
9620 // XXXbz ideally, this would do all the pushing of various
9621 // containing blocks as needed, so callers don't have to do it...
9622
9623 // Check that our parent frame is a block before allowing ::first-letter/line.
9624 // E.g. <button style="display:grid"> should not allow it.
9625 const bool allowFirstPseudos =
9626 aAllowBlockStyles && aFrame->IsBlockFrameOrSubclass();
9627 bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
9628 if (allowFirstPseudos) {
9629 ShouldHaveSpecialBlockStyle(aContent, aComputedStyle, &haveFirstLetterStyle,
9630 &haveFirstLineStyle);
9631 }
9632
9633 AutoFrameConstructionItemList itemsToConstruct(this);
9634 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
9635
9636 // If we have first-letter or first-line style then frames can get
9637 // moved around so don't set these flags.
9638 if (allowFirstPseudos && !haveFirstLetterStyle && !haveFirstLineStyle) {
9639 itemsToConstruct.SetLineBoundaryAtStart(true);
9640 itemsToConstruct.SetLineBoundaryAtEnd(true);
9641 }
9642
9643 // Create any anonymous frames we need here.
9644 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
9645 GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
9646#ifdef DEBUG1
9647 for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
9648 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"
, 9649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9649; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9649 "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"
, 9649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9649; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9650 }
9651#endif
9652 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
9653 itemsToConstruct, pageNameTracker);
9654
9655 nsBlockFrame* listItem = nullptr;
9656 bool isOutsideMarker = false;
9657 if (!aPossiblyLeafFrame->IsLeaf()) {
9658 // :before/:after content should have the same style parent as normal kids.
9659 //
9660 // Note that we don't use this style for looking up things like special
9661 // block styles because in some cases involving table pseudo-frames it has
9662 // nothing to do with the parent frame's desired behavior.
9663 auto* styleParentFrame =
9664 nsIFrame::CorrectStyleParentFrame(aFrame, PseudoStyleType::NotPseudo);
9665 ComputedStyle* computedStyle = styleParentFrame->Style();
9666
9667 if (aCanHaveGeneratedContent) {
9668 if (computedStyle->StyleDisplay()->IsListItem() &&
9669 (listItem = do_QueryFrame(aFrame)) &&
9670 !styleParentFrame->IsFieldSetFrame()) {
9671 isOutsideMarker = computedStyle->StyleList()->mListStylePosition ==
9672 StyleListStylePosition::Outside;
9673 ItemFlags extraFlags;
9674 if (isOutsideMarker) {
9675 extraFlags += ItemFlag::IsForOutsideMarker;
9676 }
9677 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9678 *computedStyle, PseudoStyleType::marker,
9679 itemsToConstruct, extraFlags);
9680 }
9681 // Probe for generated content before
9682 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9683 *computedStyle, PseudoStyleType::before,
9684 itemsToConstruct);
9685 }
9686
9687 const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth)(__builtin_expect(!!(mCurrentDepth < kMaxDepth), 1));
9688 if (!addChildItems) {
9689 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"
, 9689)
;
9690 }
9691
9692 FlattenedChildIterator iter(aContent);
9693 const InsertionPoint insertion(aFrame, aContent);
9694 for (nsIContent* child = iter.GetNextChild(); child;
9695 child = iter.GetNextChild()) {
9696 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"
, 9697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9697; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9697 "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"
, 9697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9697; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9698 if (addChildItems) {
9699 AddFrameConstructionItems(aState, child, iter.ShadowDOMInvolved(),
9700 *computedStyle, insertion, itemsToConstruct);
9701 } else {
9702 ClearLazyBits(child, child->GetNextSibling());
9703 }
9704 }
9705 itemsToConstruct.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
9706
9707 if (aCanHaveGeneratedContent) {
9708 // Probe for generated content after
9709 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9710 *computedStyle, PseudoStyleType::after,
9711 itemsToConstruct);
9712 }
9713 } else {
9714 ClearLazyBits(aContent->GetFirstChild(), nullptr);
9715 }
9716
9717 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
9718 /* aParentIsWrapperAnonBox = */ false,
9719 aFrameList);
9720
9721 if (listItem) {
9722 if (auto* markerFrame = nsLayoutUtils::GetMarkerFrame(aContent)) {
9723 for (auto* childFrame : aFrameList) {
9724 if (markerFrame == childFrame) {
9725 if (isOutsideMarker) {
9726 // SetMarkerFrameForListItem will add childFrame to the
9727 // FrameChildListID::Bullet
9728 aFrameList.RemoveFrame(childFrame);
9729 auto* grandParent = listItem->GetParent()->GetParent();
9730 if (listItem->Style()->GetPseudoType() ==
9731 PseudoStyleType::columnContent &&
9732 grandParent && grandParent->IsColumnSetWrapperFrame()) {
9733 listItem = do_QueryFrame(grandParent);
9734 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"
, 9736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9735 "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"
, 9736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9736 "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"
, 9736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9737 childFrame->SetParent(listItem);
9738 }
9739 }
9740 listItem->SetMarkerFrameForListItem(childFrame);
9741 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"
, 9741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem->HasOutsideMarker() == isOutsideMarker"
")"); do { *((volatile int*)__null) = 9741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9742#ifdef ACCESSIBILITY1
9743 if (nsAccessibilityService* accService = GetAccService()) {
9744 auto* marker = markerFrame->GetContent();
9745 accService->ContentRangeInserted(mPresShell, marker, nullptr);
9746 }
9747#endif
9748 break;
9749 }
9750 }
9751 }
9752 }
9753
9754 if (haveFirstLetterStyle) {
9755 WrapFramesInFirstLetterFrame(aFrame, aFrameList);
9756 }
9757 if (haveFirstLineStyle) {
9758 WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr, aFrameList);
9759 }
9760}
9761
9762//----------------------------------------------------------------------
9763
9764// Support for :first-line style
9765
9766// Special routine to handle placing a list of frames into a block
9767// frame that has first-line style. The routine ensures that the first
9768// collection of inline frames end up in a first-line frame.
9769// NOTE: aState may have containing block information related to a
9770// different part of the frame tree than where the first line occurs.
9771// In particular aState may be set up for where ContentInserted or
9772// ContentAppended is inserting content, which may be some
9773// non-first-in-flow continuation of the block to which the first-line
9774// belongs. So this function needs to be careful about how it uses
9775// aState.
9776void nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
9777 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9778 nsContainerFrame* aBlockFrame, nsFirstLineFrame* aLineFrame,
9779 nsFrameList& aFrameList) {
9780 // Extract any initial inline frames from aFrameList so we can put them
9781 // in the first-line.
9782 nsFrameList firstLineChildren =
9783 aFrameList.Split([](nsIFrame* f) { return !f->IsInlineOutside(); });
9784
9785 if (firstLineChildren.IsEmpty()) {
9786 // Nothing is supposed to go into the first-line; nothing to do
9787 return;
9788 }
9789
9790 if (!aLineFrame) {
9791 // Create line frame
9792 ComputedStyle* parentStyle = nsIFrame::CorrectStyleParentFrame(
9793 aBlockFrame, PseudoStyleType::firstLine)
9794 ->Style();
9795 RefPtr<ComputedStyle> firstLineStyle =
9796 GetFirstLineStyle(aBlockContent, parentStyle);
9797
9798 aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
9799
9800 // Initialize the line frame
9801 InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
9802
9803 // The lineFrame will be the block's first child; the rest of the
9804 // frame list (after lastInlineFrame) will be the second and
9805 // subsequent children; insert lineFrame into aFrameList.
9806 aFrameList.InsertFrame(nullptr, nullptr, aLineFrame);
9807
9808 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"
, 9809); MOZ_PretendNoReturn(); } } while (0)
9809 "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"
, 9809); MOZ_PretendNoReturn(); } } while (0)
;
9810 }
9811
9812 // Give the inline frames to the lineFrame <b>after</b> reparenting them
9813 ReparentFrames(this, aLineFrame, firstLineChildren, true);
9814 if (aLineFrame->PrincipalChildList().IsEmpty() &&
9815 aLineFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
9816 aLineFrame->SetInitialChildList(FrameChildListID::Principal,
9817 std::move(firstLineChildren));
9818 } else {
9819 AppendFrames(aLineFrame, FrameChildListID::Principal,
9820 std::move(firstLineChildren));
9821 }
9822}
9823
9824// Special routine to handle appending a new frame to a block frame's
9825// child list. Takes care of placing the new frame into the right
9826// place when first-line style is present.
9827void nsCSSFrameConstructor::AppendFirstLineFrames(
9828 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9829 nsContainerFrame* aBlockFrame, nsFrameList& aFrameList) {
9830 // It's possible that aBlockFrame needs to have a first-line frame
9831 // created because it doesn't currently have any children.
9832 const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
9833 if (blockKids.IsEmpty()) {
9834 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, nullptr,
9835 aFrameList);
9836 return;
9837 }
9838
9839 // Examine the last block child - if it's a first-line frame then
9840 // appended frames need special treatment.
9841 nsIFrame* lastBlockKid = blockKids.LastChild();
9842 if (!lastBlockKid->IsLineFrame()) {
9843 // No first-line frame at the end of the list, therefore there is
9844 // an intervening block between any first-line frame the frames
9845 // we are appending. Therefore, we don't need any special
9846 // treatment of the appended frames.
9847 return;
9848 }
9849
9850 nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
9851 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, lineFrame,
9852 aFrameList);
9853}
9854
9855void nsCSSFrameConstructor::CheckForFirstLineInsertion(
9856 nsIFrame* aParentFrame, nsFrameList& aFrameList) {
9857 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"
, 9858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9858; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
9858 "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"
, 9858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9858; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9859
9860 if (aFrameList.IsEmpty()) {
9861 // Happens often enough, with the caption stuff. No need to do the ancestor
9862 // walk here.
9863 return;
9864 }
9865
9866 class RestyleManager* restyleManager = RestyleManager();
9867
9868 // Check whether there's a ::first-line on the path up from aParentFrame.
9869 // Note that we can't stop until we've run out of ancestors with
9870 // pseudo-element data, because the first-letter might be somewhere way up the
9871 // tree; in particular it might be past our containing block.
9872 nsIFrame* ancestor = aParentFrame;
9873 while (ancestor) {
9874 if (!ancestor->Style()->HasPseudoElementData()) {
9875 // We know we won't find a ::first-line now.
9876 return;
9877 }
9878
9879 if (!ancestor->IsLineFrame()) {
9880 ancestor = ancestor->GetParent();
9881 continue;
9882 }
9883
9884 if (!ancestor->Style()->IsPseudoElement()) {
9885 // This is a continuation lineframe, not the first line; no need to do
9886 // anything to the styles.
9887 return;
9888 }
9889
9890 // Fix up the styles of aFrameList for ::first-line.
9891 for (nsIFrame* f : aFrameList) {
9892 restyleManager->ReparentComputedStyleForFirstLine(f);
9893 }
9894 return;
9895 }
9896}
9897
9898//----------------------------------------------------------------------
9899
9900// First-letter support
9901
9902// Determine how many characters in the text fragment apply to the
9903// first letter
9904static int32_t FirstLetterCount(const nsTextFragment* aFragment) {
9905 int32_t count = 0;
9906 int32_t firstLetterLength = 0;
9907
9908 const uint32_t n = aFragment->GetLength();
9909 for (uint32_t i = 0; i < n; i++) {
9910 const char16_t ch = aFragment->CharAt(i);
9911 // FIXME: take content language into account when deciding whitespace.
9912 if (dom::IsSpaceCharacter(ch)) {
9913 if (firstLetterLength) {
9914 break;
9915 }
9916 count++;
9917 continue;
9918 }
9919 // XXX I18n
9920 if ((ch == '\'') || (ch == '\"')) {
9921 if (firstLetterLength) {
9922 break;
9923 }
9924 // keep looping
9925 firstLetterLength = 1;
9926 } else {
9927 count++;
9928 break;
9929 }
9930 }
9931
9932 return count;
9933}
9934
9935static bool NeedFirstLetterContinuation(Text* aText) {
9936 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"
, 9936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aText" ") ("
"null ptr" ")"); do { *((volatile int*)__null) = 9936; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
9937 int32_t flc = FirstLetterCount(&aText->TextFragment());
9938 int32_t tl = aText->TextDataLength();
9939 return flc < tl;
9940}
9941
9942static bool IsFirstLetterContent(Text* aText) {
9943 return aText->TextDataLength() && !aText->TextIsOnlyWhitespace();
9944}
9945
9946/**
9947 * Create a letter frame, only make it a floating frame.
9948 */
9949nsFirstLetterFrame* nsCSSFrameConstructor::CreateFloatingLetterFrame(
9950 nsFrameConstructorState& aState, Text* aTextContent, nsIFrame* aTextFrame,
9951 nsContainerFrame* aParentFrame, ComputedStyle* aParentStyle,
9952 ComputedStyle* aComputedStyle, nsFrameList& aResult) {
9953 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"
, 9953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentStyle"
")"); do { *((volatile int*)__null) = 9953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9954
9955 nsFirstLetterFrame* letterFrame =
9956 NS_NewFloatingFirstLetterFrame(mPresShell, aComputedStyle);
9957 // We don't want to use a text content for a non-text frame (because we want
9958 // its primary frame to be a text frame).
9959 nsIContent* letterContent = aParentFrame->GetContent();
9960 nsContainerFrame* containingBlock =
9961 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
9962 InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
9963
9964 // Init the text frame to refer to the letter frame.
9965 //
9966 // Make sure we get a proper style for it (the one passed in is for the letter
9967 // frame and will have the float property set on it; the text frame shouldn't
9968 // have that set).
9969 ServoStyleSet* styleSet = mPresShell->StyleSet();
9970 RefPtr<ComputedStyle> textSC =
9971 styleSet->ResolveStyleForText(aTextContent, aComputedStyle);
9972 aTextFrame->SetComputedStyleWithoutNotification(textSC);
9973 InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
9974
9975 // And then give the text frame to the letter frame
9976 SetInitialSingleChild(letterFrame, aTextFrame);
9977
9978 // See if we will need to continue the text frame (does it contain
9979 // more than just the first-letter text or not?) If it does, then we
9980 // create (in advance) a continuation frame for it.
9981 nsIFrame* nextTextFrame = nullptr;
9982 if (NeedFirstLetterContinuation(aTextContent)) {
9983 // Create continuation
9984 nextTextFrame = CreateContinuingFrame(aTextFrame, aParentFrame);
9985 RefPtr<ComputedStyle> newSC =
9986 styleSet->ResolveStyleForText(aTextContent, aParentStyle);
9987 nextTextFrame->SetComputedStyle(newSC);
9988 }
9989
9990 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"
, 9990); MOZ_PretendNoReturn(); } } while (0)
;
9991 // Put the new float before any of the floats in the block we're doing
9992 // first-letter for, that is, before any floats whose parent is
9993 // containingBlock.
9994 nsIFrame* prevSibling = nullptr;
9995 for (nsIFrame* f : aState.mFloatedList) {
9996 if (f->GetParent() == containingBlock) {
9997 break;
9998 }
9999 prevSibling = f;
10000 }
10001
10002 aState.AddChild(letterFrame, aResult, letterContent, aParentFrame, false,
10003 true, true, prevSibling);
10004
10005 if (nextTextFrame) {
10006 aResult.AppendFrame(nullptr, nextTextFrame);
10007 }
10008
10009 return letterFrame;
10010}
10011
10012/**
10013 * Create a new letter frame for aTextFrame. The letter frame will be
10014 * a child of aParentFrame.
10015 */
10016void nsCSSFrameConstructor::CreateLetterFrame(
10017 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10018 Text* aTextContent, nsContainerFrame* aParentFrame, nsFrameList& aResult) {
10019 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"
, 10019); MOZ_PretendNoReturn(); } } while (0)
;
10020
10021 // Get a ComputedStyle for the first-letter-frame.
10022 //
10023 // Keep this in sync with nsBlockFrame::UpdatePseudoElementStyles.
10024 nsIFrame* parentFrame = nsIFrame::CorrectStyleParentFrame(
10025 aParentFrame, PseudoStyleType::firstLetter);
10026
10027 ComputedStyle* parentComputedStyle = parentFrame->Style();
10028 ComputedStyle* parentComputedStyleIgnoringFirstLine = parentComputedStyle;
10029 if (parentFrame->IsLineFrame()) {
10030 parentComputedStyleIgnoringFirstLine =
10031 nsIFrame::CorrectStyleParentFrame(aBlockFrame,
10032 PseudoStyleType::firstLetter)
10033 ->Style();
10034 }
10035
10036 // Use content from containing block so that we can actually
10037 // find a matching style rule.
10038 nsIContent* blockContent = aBlockFrame->GetContent();
10039
10040 // Create first-letter style rule, ignoring first line. If we already have a
10041 // first-line we'll reparent the style below.
10042 RefPtr<ComputedStyle> sc =
10043 GetFirstLetterStyle(blockContent, parentComputedStyleIgnoringFirstLine);
10044
10045 if (sc) {
10046 if (parentComputedStyleIgnoringFirstLine != parentComputedStyle) {
10047 sc = mPresShell->StyleSet()->ReparentComputedStyle(
10048 sc, parentComputedStyle, parentComputedStyle,
10049 blockContent->AsElement());
10050 }
10051
10052 RefPtr<ComputedStyle> textSC =
10053 mPresShell->StyleSet()->ResolveStyleForText(aTextContent, sc);
10054
10055 // Create a new text frame (the original one will be discarded)
10056 // pass a temporary stylecontext, the correct one will be set
10057 // later. Start off by unsetting the primary frame for
10058 // aTextContent, so it's no longer pointing to the to-be-destroyed
10059 // frame.
10060 // XXXbz it would be really nice to destroy the old frame _first_,
10061 // then create the new one, so we could avoid this hack.
10062 aTextContent->SetPrimaryFrame(nullptr);
10063 nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
10064
10065 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"
, 10066); MOZ_PretendNoReturn(); } } while (0)
10066 "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"
, 10066); MOZ_PretendNoReturn(); } } while (0)
;
10067 nsFrameConstructorState state(
10068 mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
10069 GetAbsoluteContainingBlock(aParentFrame, ABS_POS), aBlockContinuation);
10070
10071 // Create the right type of first-letter frame
10072 const nsStyleDisplay* display = sc->StyleDisplay();
10073 nsFirstLetterFrame* letterFrame;
10074 if (display->IsFloatingStyle() && !aParentFrame->IsInSVGTextSubtree()) {
10075 // Make a floating first-letter frame
10076 letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
10077 aParentFrame, parentComputedStyle,
10078 sc, aResult);
10079 } else {
10080 // Make an inflow first-letter frame
10081 letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
10082
10083 // Initialize the first-letter-frame. We don't want to use a text
10084 // content for a non-text frame (because we want its primary frame to
10085 // be a text frame).
10086 nsIContent* letterContent = aParentFrame->GetContent();
10087 letterFrame->Init(letterContent, aParentFrame, nullptr);
10088
10089 InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
10090
10091 SetInitialSingleChild(letterFrame, textFrame);
10092 aResult.Clear();
10093 aResult.AppendFrame(nullptr, letterFrame);
10094 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"
, 10095); MOZ_PretendNoReturn(); } } while (0)
10095 "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"
, 10095); MOZ_PretendNoReturn(); } } while (0)
;
10096 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10097 }
10098 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"
, 10100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10100; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10099 !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"
, 10100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10100; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10100 "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"
, 10100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10100; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10101 auto parent =
10102 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10103 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10104 parent = static_cast<nsContainerFrame*>(
10105 parent->GetParent()->FirstContinuation());
10106 }
10107 parent->SetHasFirstLetterChild();
10108 aBlockFrame->SetProperty(nsContainerFrame::FirstLetterProperty(),
10109 letterFrame);
10110 aTextContent->SetPrimaryFrame(textFrame);
10111 }
10112}
10113
10114void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10115 nsContainerFrame* aBlockFrame, nsFrameList& aBlockFrames) {
10116 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10117
10118 nsContainerFrame* parentFrame = nullptr;
10119 nsIFrame* textFrame = nullptr;
10120 nsIFrame* prevFrame = nullptr;
10121 nsFrameList letterFrames;
10122 bool stopLooking = false;
10123 WrapFramesInFirstLetterFrame(
10124 aBlockFrame, aBlockFrame, aBlockFrame, aBlockFrames.FirstChild(),
10125 &parentFrame, &textFrame, &prevFrame, letterFrames, &stopLooking);
10126 if (!parentFrame) {
10127 return;
10128 }
10129 DestroyContext context(mPresShell);
10130 if (parentFrame == aBlockFrame) {
10131 // Take textFrame out of the block's frame list and substitute the
10132 // letter frame(s) instead.
10133 aBlockFrames.DestroyFrame(context, textFrame);
10134 aBlockFrames.InsertFrames(nullptr, prevFrame, std::move(letterFrames));
10135 } else {
10136 // Take the old textFrame out of the inline parent's child list
10137 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10138
10139 // Insert in the letter frame(s)
10140 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10141 std::move(letterFrames));
10142 }
10143}
10144
10145void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10146 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10147 nsContainerFrame* aParentFrame, nsIFrame* aParentFrameList,
10148 nsContainerFrame** aModifiedParent, nsIFrame** aTextFrame,
10149 nsIFrame** aPrevFrame, nsFrameList& aLetterFrames, bool* aStopLooking) {
10150 nsIFrame* prevFrame = nullptr;
10151 nsIFrame* frame = aParentFrameList;
10152
10153 // This loop attempts to implement "Finding the First Letter":
10154 // https://drafts.csswg.org/css-pseudo-4/#application-in-css
10155 // FIXME: we don't handle nested blocks correctly yet though (bug 214004)
10156 while (frame) {
10157 nsIFrame* nextFrame = frame->GetNextSibling();
10158
10159 // Skip all ::markers and placeholders.
10160 if (frame->Style()->GetPseudoType() == PseudoStyleType::marker ||
10161 frame->IsPlaceholderFrame()) {
10162 prevFrame = frame;
10163 frame = nextFrame;
10164 continue;
10165 }
10166 LayoutFrameType frameType = frame->Type();
10167 if (LayoutFrameType::Text == frameType) {
10168 // Wrap up first-letter content in a letter frame
10169 Text* textContent = frame->GetContent()->AsText();
10170 if (IsFirstLetterContent(textContent)) {
10171 // Create letter frame to wrap up the text
10172 CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
10173 aParentFrame, aLetterFrames);
10174
10175 // Provide adjustment information for parent
10176 *aModifiedParent = aParentFrame;
10177 *aTextFrame = frame;
10178 *aPrevFrame = prevFrame;
10179 *aStopLooking = true;
10180 return;
10181 }
10182 } else if (IsInlineFrame(frame) && frameType != LayoutFrameType::Br) {
10183 nsIFrame* kids = frame->PrincipalChildList().FirstChild();
10184 WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
10185 static_cast<nsContainerFrame*>(frame), kids,
10186 aModifiedParent, aTextFrame, aPrevFrame,
10187 aLetterFrames, aStopLooking);
10188 if (*aStopLooking) {
10189 return;
10190 }
10191 } else {
10192 // This will stop us looking to create more letter frames. For
10193 // example, maybe the frame-type is "letterFrame" or
10194 // "placeholderFrame". This keeps us from creating extra letter
10195 // frames, and also prevents us from creating letter frames when
10196 // the first real content child of a block is not text (e.g. an
10197 // image, hr, etc.)
10198 *aStopLooking = true;
10199 break;
10200 }
10201
10202 prevFrame = frame;
10203 frame = nextFrame;
10204 }
10205}
10206
10207static nsIFrame* FindFirstLetterFrame(nsIFrame* aFrame,
10208 FrameChildListID aListID) {
10209 for (nsIFrame* f : aFrame->GetChildList(aListID)) {
10210 if (f->IsLetterFrame()) {
10211 return f;
10212 }
10213 }
10214 return nullptr;
10215}
10216
10217static void ClearHasFirstLetterChildFrom(nsContainerFrame* aParentFrame) {
10218 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"
, 10218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 10218; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10219 auto* parent =
10220 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10221 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10222 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"
, 10222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10222; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10223 parent = static_cast<nsContainerFrame*>(
10224 parent->GetParent()->FirstContinuation());
10225 }
10226 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"
, 10226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10226; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10227 parent->ClearHasFirstLetterChild();
10228}
10229
10230void nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
10231 PresShell* aPresShell, nsIFrame* aBlockFrame) {
10232 // Look for the first letter frame on the FrameChildListID::Float, then
10233 // FrameChildListID::PushedFloats.
10234 nsIFrame* floatFrame =
10235 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::Float);
10236 if (!floatFrame) {
10237 floatFrame =
10238 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::PushedFloats);
10239 if (!floatFrame) {
10240 return;
10241 }
10242 }
10243
10244 // Take the text frame away from the letter frame (so it isn't
10245 // destroyed when we destroy the letter frame).
10246 nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
10247 if (!textFrame) {
10248 return;
10249 }
10250
10251 // Discover the placeholder frame for the letter frame
10252 nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame();
10253 if (!placeholderFrame) {
10254 // Somethings really wrong
10255 return;
10256 }
10257 nsContainerFrame* parentFrame = placeholderFrame->GetParent();
10258 if (!parentFrame) {
10259 // Somethings really wrong
10260 return;
10261 }
10262
10263 ClearHasFirstLetterChildFrom(parentFrame);
10264
10265 // Create a new text frame with the right style that maps all of the content
10266 // that was previously part of the letter frame (and probably continued
10267 // elsewhere).
10268 ComputedStyle* parentSC = parentFrame->Style();
10269 nsIContent* textContent = textFrame->GetContent();
10270 if (!textContent) {
10271 return;
10272 }
10273 RefPtr<ComputedStyle> newSC =
10274 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10275 nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
10276 newTextFrame->Init(textContent, parentFrame, nullptr);
10277
10278 // Destroy the old text frame's continuations (the old text frame
10279 // will be destroyed when its letter frame is destroyed).
10280 nsIFrame* frameToDelete = textFrame->LastContinuation();
10281 DestroyContext context(mPresShell);
10282 while (frameToDelete != textFrame) {
10283 nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
10284 RemoveFrame(context, FrameChildListID::Principal, frameToDelete);
10285 frameToDelete = nextFrameToDelete;
10286 }
10287
10288 nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
10289
10290 // Now that everything is set...
10291#ifdef NOISY_FIRST_LETTER
10292 printf(
10293 "RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p "
10294 "newTextFrame=%p\n",
10295 textContent.get(), textFrame, newTextFrame);
10296#endif
10297
10298 // Remove placeholder frame and the float
10299 RemoveFrame(context, FrameChildListID::Principal, placeholderFrame);
10300
10301 // Now that the old frames are gone, we can start pointing to our
10302 // new primary frame.
10303 textContent->SetPrimaryFrame(newTextFrame);
10304
10305 // Wallpaper bug 822910.
10306 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10307 if (offsetsNeedFixing) {
10308 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10309 }
10310
10311 // Insert text frame in its place
10312 InsertFrames(parentFrame, FrameChildListID::Principal, prevSibling,
10313 nsFrameList(newTextFrame, newTextFrame));
10314
10315 if (offsetsNeedFixing) {
10316 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10317 }
10318}
10319
10320void nsCSSFrameConstructor::RemoveFirstLetterFrames(
10321 PresShell* aPresShell, nsContainerFrame* aFrame,
10322 nsContainerFrame* aBlockFrame, bool* aStopLooking) {
10323 nsIFrame* prevSibling = nullptr;
10324 nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
10325
10326 while (kid) {
10327 if (kid->IsLetterFrame()) {
10328 ClearHasFirstLetterChildFrom(aFrame);
10329 nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
10330 if (!textFrame) {
10331 break;
10332 }
10333
10334 // Create a new textframe
10335 ComputedStyle* parentSC = aFrame->Style();
10336 if (!parentSC) {
10337 break;
10338 }
10339 nsIContent* textContent = textFrame->GetContent();
10340 if (!textContent) {
10341 break;
10342 }
10343 RefPtr<ComputedStyle> newSC =
10344 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10345 textFrame = NS_NewTextFrame(aPresShell, newSC);
10346 textFrame->Init(textContent, aFrame, nullptr);
10347
10348 DestroyContext context(mPresShell);
10349
10350 // Next rip out the kid and replace it with the text frame
10351 RemoveFrame(context, FrameChildListID::Principal, kid);
10352
10353 // Now that the old frames are gone, we can start pointing to our
10354 // new primary frame.
10355 textContent->SetPrimaryFrame(textFrame);
10356
10357 // Wallpaper bug 822910.
10358 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10359 if (offsetsNeedFixing) {
10360 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10361 }
10362
10363 // Insert text frame in its place
10364 InsertFrames(aFrame, FrameChildListID::Principal, prevSibling,
10365 nsFrameList(textFrame, textFrame));
10366
10367 if (offsetsNeedFixing) {
10368 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10369 }
10370
10371 *aStopLooking = true;
10372 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"
, 10373); MOZ_PretendNoReturn(); } } while (0)
10373 "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"
, 10373); MOZ_PretendNoReturn(); } } while (0)
;
10374 aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10375 break;
10376 }
10377 if (IsInlineFrame(kid)) {
10378 nsContainerFrame* kidAsContainerFrame = do_QueryFrame(kid);
10379 if (kidAsContainerFrame) {
10380 // Look inside child inline frame for the letter frame.
10381 RemoveFirstLetterFrames(aPresShell, kidAsContainerFrame, aBlockFrame,
10382 aStopLooking);
10383 if (*aStopLooking) {
10384 break;
10385 }
10386 }
10387 }
10388 prevSibling = kid;
10389 kid = kid->GetNextSibling();
10390 }
10391}
10392
10393void nsCSSFrameConstructor::RemoveLetterFrames(PresShell* aPresShell,
10394 nsContainerFrame* aBlockFrame) {
10395 aBlockFrame =
10396 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10397 aBlockFrame->RemoveProperty(nsContainerFrame::FirstLetterProperty());
10398 nsContainerFrame* continuation = aBlockFrame;
10399
10400 bool stopLooking = false;
10401 do {
10402 RemoveFloatingFirstLetterFrames(aPresShell, continuation);
10403 RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame,
10404 &stopLooking);
10405 if (stopLooking) {
10406 break;
10407 }
10408 continuation =
10409 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10410 } while (continuation);
10411}
10412
10413// Fixup the letter frame situation for the given block
10414void nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame) {
10415 aBlockFrame =
10416 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10417 nsContainerFrame* continuation = aBlockFrame;
10418
10419 nsContainerFrame* parentFrame = nullptr;
10420 nsIFrame* textFrame = nullptr;
10421 nsIFrame* prevFrame = nullptr;
10422 nsFrameList letterFrames;
10423 bool stopLooking = false;
10424 do {
10425 // XXX shouldn't this bit be set already (bug 408493), assert instead?
10426 continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10427 WrapFramesInFirstLetterFrame(
10428 aBlockFrame, continuation, continuation,
10429 continuation->PrincipalChildList().FirstChild(), &parentFrame,
10430 &textFrame, &prevFrame, letterFrames, &stopLooking);
10431 if (stopLooking) {
10432 break;
10433 }
10434 continuation =
10435 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10436 } while (continuation);
10437
10438 if (!parentFrame) {
10439 return;
10440 }
10441 // Take the old textFrame out of the parent's child list
10442 DestroyContext context(mPresShell);
10443 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10444
10445 // Insert in the letter frame(s)
10446 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10447 std::move(letterFrames));
10448}
10449
10450//----------------------------------------------------------------------
10451
10452void nsCSSFrameConstructor::ConstructBlock(
10453 nsFrameConstructorState& aState, nsIContent* aContent,
10454 nsContainerFrame* aParentFrame, nsContainerFrame* aContentParentFrame,
10455 ComputedStyle* aComputedStyle, nsContainerFrame** aNewFrame,
10456 nsFrameList& aFrameList, nsIFrame* aPositionedFrameForAbsPosContainer) {
10457 // clang-format off
10458 //
10459 // If a block frame is in a multi-column subtree, its children may need to
10460 // be chopped into runs of blocks containing column-spans and runs of
10461 // blocks containing no column-spans. Each run containing column-spans
10462 // will be wrapped by an anonymous block. See CreateColumnSpanSiblings() for
10463 // the implementation.
10464 //
10465 // If a block frame is a multi-column container, its children will need to
10466 // be processed as above. Moreover, it creates a ColumnSetWrapperFrame as
10467 // its outermost frame, and its children which have no
10468 // -moz-column-span-wrapper pseudo will be wrapped in ColumnSetFrames. See
10469 // FinishBuildingColumns() for the implementation.
10470 //
10471 // The multi-column subtree maintains the following invariants:
10472 //
10473 // 1) All the frames have the frame state bit
10474 // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR set, except for top-level
10475 // ColumnSetWrapperFrame and those children in the column-span subtrees.
10476 //
10477 // 2) The first and last frame under ColumnSetWrapperFrame are always
10478 // ColumnSetFrame.
10479 //
10480 // 3) ColumnSetFrames are linked together as continuations.
10481 //
10482 // 4) Those column-span wrappers are *not* linked together with themselves nor
10483 // with the original block frame. The continuation chain consists of the
10484 // original block frame and the original block's continuations wrapping
10485 // non-column-spans.
10486 //
10487 // For example, this HTML
10488 // <div id="x" style="column-count: 2;">
10489 // <div style="column-span: all">a</div>
10490 // <div id="y">
10491 // b
10492 // <div style="column-span: all">c</div>
10493 // <div style="column-span: all">d</div>
10494 // e
10495 // </div>
10496 // </div>
10497 // <div style="column-span: all">f</div>
10498 //
10499 // yields the following frame tree.
10500 //
10501 // A) ColumnSetWrapper (original style)
10502 // B) ColumnSet (-moz-column-set) <-- always created by BeginBuildingColumns
10503 // C) Block (-moz-column-content)
10504 // D) Block (-moz-column-span-wrapper, created by x)
10505 // E) Block (div)
10506 // F) Text ("a")
10507 // G) ColumnSet (-moz-column-set)
10508 // H) Block (-moz-column-content, created by x)
10509 // I) Block (div, y)
10510 // J) Text ("b")
10511 // K) Block (-moz-column-span-wrapper, created by x)
10512 // L) Block (-moz-column-span-wrapper, created by y)
10513 // M) Block (div, new BFC)
10514 // N) Text ("c")
10515 // O) Block (div, new BFC)
10516 // P) Text ("d")
10517 // Q) ColumnSet (-moz-column-set)
10518 // R) Block (-moz-column-content, created by x)
10519 // S) Block (div, y)
10520 // T) Text ("e")
10521 // U) Block (div, new BFC) <-- not in multi-column hierarchy
10522 // V) Text ("f")
10523 //
10524 // ColumnSet linkage described in 3): B -> G -> Q
10525 //
10526 // Block linkage described in 4): C -> H -> R and I -> S
10527 //
10528 // clang-format on
10529
10530 nsBlockFrame* blockFrame = do_QueryFrame(*aNewFrame);
10531 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"
, 10531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockFrame && blockFrame->IsBlockFrame()"
") (" "not a block frame?" ")"); do { *((volatile int*)__null
) = 10531; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
10532
10533 // Create column hierarchy if necessary.
10534 const bool needsColumn =
10535 aComputedStyle->StyleColumn()->IsColumnContainerStyle();
10536 if (needsColumn) {
10537 *aNewFrame = BeginBuildingColumns(aState, aContent, aParentFrame,
10538 blockFrame, aComputedStyle);
10539
10540 if (aPositionedFrameForAbsPosContainer == blockFrame) {
10541 aPositionedFrameForAbsPosContainer = *aNewFrame;
10542 }
10543 } else {
10544 // No need to create column hierarchy. Initialize block frame.
10545 blockFrame->SetComputedStyleWithoutNotification(aComputedStyle);
10546 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
10547 }
10548
10549 aState.AddChild(*aNewFrame, aFrameList, aContent,
10550 aContentParentFrame ? aContentParentFrame : aParentFrame);
10551 if (!mRootElementFrame) {
10552 mRootElementFrame = *aNewFrame;
10553 }
10554
10555 // We should make the outer frame be the absolute containing block,
10556 // if one is required. We have to do this because absolute
10557 // positioning must be computed with respect to the CSS dimensions
10558 // of the element, which are the dimensions of the outer block. But
10559 // we can't really do that because only blocks can have absolute
10560 // children. So use the block and try to compensate with hacks
10561 // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
10562 nsFrameConstructorSaveState absoluteSaveState;
10563 (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10564 if (aPositionedFrameForAbsPosContainer) {
10565 aState.PushAbsoluteContainingBlock(
10566 *aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
10567 }
10568
10569 nsFrameConstructorSaveState floatSaveState;
10570 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
10571
10572 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10573 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10574 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10575 }
10576
10577 // Process the child content
10578 nsFrameList childList;
10579 ProcessChildren(aState, aContent, aComputedStyle, blockFrame, true, childList,
10580 true);
10581
10582 if (!MayNeedToCreateColumnSpanSiblings(blockFrame, childList)) {
10583 // No need to create column-span siblings.
10584 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10585 std::move(childList));
10586 return;
10587 }
10588
10589 // Extract any initial non-column-span kids, and put them in block frame's
10590 // child list.
10591 nsFrameList initialNonColumnSpanKids =
10592 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10593 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10594 std::move(initialNonColumnSpanKids));
10595
10596 if (childList.IsEmpty()) {
10597 // No more kids to process (there weren't any column-span kids).
10598 return;
10599 }
10600
10601 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
10602 aState, blockFrame, childList,
10603 // If we're constructing a column container, pass nullptr as
10604 // aPositionedFrame to forbid reparenting absolute/fixed positioned frames
10605 // to column contents or column-span wrappers.
10606 needsColumn ? nullptr : aPositionedFrameForAbsPosContainer);
10607
10608 if (needsColumn) {
10609 // We're constructing a column container; need to finish building it.
10610 FinishBuildingColumns(aState, *aNewFrame, blockFrame, columnSpanSiblings);
10611 } else {
10612 // We're constructing a normal block which has column-span children in a
10613 // column hierarchy such as "x" in the following example.
10614 //
10615 // <div style="column-count: 2">
10616 // <div id="x">
10617 // <div>normal child</div>
10618 // <div style="column-span">spanner</div>
10619 // </div>
10620 // </div>
10621 aFrameList.AppendFrames(nullptr, std::move(columnSpanSiblings));
10622 }
10623
10624 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"
, 10625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10625; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10625 "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"
, 10625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10625; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10626}
10627
10628nsBlockFrame* nsCSSFrameConstructor::BeginBuildingColumns(
10629 nsFrameConstructorState& aState, nsIContent* aContent,
10630 nsContainerFrame* aParentFrame, nsContainerFrame* aColumnContent,
10631 ComputedStyle* aComputedStyle) {
10632 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"
, 10633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10633; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10633 "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"
, 10633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10633; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10634 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"
, 10635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10635; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
10635 "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"
, 10635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10635; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10636
10637 // The initial column hierarchy looks like this:
10638 //
10639 // ColumnSetWrapper (original style)
10640 // ColumnSet (-moz-column-set)
10641 // Block (-moz-column-content)
10642 //
10643 nsBlockFrame* columnSetWrapper = NS_NewColumnSetWrapperFrame(
10644 mPresShell, aComputedStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10645 InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetWrapper);
10646 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10647 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10648 columnSetWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10649 }
10650
10651 AutoFrameConstructionPageName pageNameTracker(aState, columnSetWrapper);
10652 RefPtr<ComputedStyle> columnSetStyle =
10653 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10654 PseudoStyleType::columnSet, aComputedStyle);
10655 nsContainerFrame* columnSet = NS_NewColumnSetFrame(
10656 mPresShell, columnSetStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10657 InitAndRestoreFrame(aState, aContent, columnSetWrapper, columnSet);
10658 columnSet->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10659
10660 RefPtr<ComputedStyle> blockStyle =
10661 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10662 PseudoStyleType::columnContent, columnSetStyle);
10663 aColumnContent->SetComputedStyleWithoutNotification(blockStyle);
10664 InitAndRestoreFrame(aState, aContent, columnSet, aColumnContent);
10665 aColumnContent->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10666
10667 // Set up the parent-child chain.
10668 SetInitialSingleChild(columnSetWrapper, columnSet);
10669 SetInitialSingleChild(columnSet, aColumnContent);
10670
10671 return columnSetWrapper;
10672}
10673
10674void nsCSSFrameConstructor::FinishBuildingColumns(
10675 nsFrameConstructorState& aState, nsContainerFrame* aColumnSetWrapper,
10676 nsContainerFrame* aColumnContent, nsFrameList& aColumnContentSiblings) {
10677 nsContainerFrame* prevColumnSet = aColumnContent->GetParent();
10678
10679 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"
, 10681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10681; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10680 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"
, 10681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10681; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10681 "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"
, 10681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10681; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10682
10683 // Tag the first ColumnSet to have column-span siblings so that the bit can
10684 // propagate to all the continuations. We don't want the last ColumnSet to
10685 // have this bit, so we will unset the bit for it at the end of this function.
10686 prevColumnSet->SetHasColumnSpanSiblings(true);
10687
10688 nsFrameList finalList;
10689 while (aColumnContentSiblings.NotEmpty()) {
10690 nsIFrame* f = aColumnContentSiblings.RemoveFirstChild();
10691 if (f->IsColumnSpan()) {
10692 // Do nothing for column-span wrappers. Just move it to the final
10693 // items.
10694 finalList.AppendFrame(aColumnSetWrapper, f);
10695 } else {
10696 auto* continuingColumnSet = static_cast<nsContainerFrame*>(
10697 CreateContinuingFrame(prevColumnSet, aColumnSetWrapper, false));
10698 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"
, 10699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10699 "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"
, 10699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10700
10701 f->SetParent(continuingColumnSet);
10702 SetInitialSingleChild(continuingColumnSet, f);
10703 finalList.AppendFrame(aColumnSetWrapper, continuingColumnSet);
10704 prevColumnSet = continuingColumnSet;
10705 }
10706 }
10707
10708 // Unset the bit because the last ColumnSet has no column-span siblings.
10709 prevColumnSet->SetHasColumnSpanSiblings(false);
10710
10711 aColumnSetWrapper->AppendFrames(FrameChildListID::Principal,
10712 std::move(finalList));
10713}
10714
10715bool nsCSSFrameConstructor::MayNeedToCreateColumnSpanSiblings(
10716 nsContainerFrame* aBlockFrame, const nsFrameList& aChildList) {
10717 if (!aBlockFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10718 // The block frame isn't in a multi-column block formatting context.
10719 return false;
10720 }
10721
10722 if (ShouldSuppressColumnSpanDescendants(aBlockFrame)) {
10723 // No need to create column-span siblings for a frame that suppresses them.
10724 return false;
10725 }
10726
10727 if (aChildList.IsEmpty()) {
10728 // No child needs to be processed.
10729 return false;
10730 }
10731
10732 // Need to actually look into the child list.
10733 return true;
10734}
10735
10736nsFrameList nsCSSFrameConstructor::CreateColumnSpanSiblings(
10737 nsFrameConstructorState& aState, nsContainerFrame* aInitialBlock,
10738 nsFrameList& aChildList, nsIFrame* aPositionedFrame) {
10739 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"
, 10739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInitialBlock->IsBlockFrameOrSubclass()"
")"); do { *((volatile int*)__null) = 10739; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10740 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"
, 10740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 10740; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10741
10742 nsIContent* const content = aInitialBlock->GetContent();
10743 nsContainerFrame* const parentFrame = aInitialBlock->GetParent();
10744 const bool isInitialBlockFloatCB = aInitialBlock->IsFloatContainingBlock();
10745
10746 nsFrameList siblings;
10747 nsContainerFrame* lastNonColumnSpanWrapper = aInitialBlock;
10748
10749 // Tag the first non-column-span wrapper to have column-span siblings so that
10750 // the bit can propagate to all the continuations. We don't want the last
10751 // wrapper to have this bit, so we will unset the bit for it at the end of
10752 // this function.
10753 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(true);
10754 do {
10755 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"
, 10755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Why call this if child list is empty?" ")"); do { *((
volatile int*)__null) = 10755; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10756 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"
, 10757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10757; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10757 "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"
, 10757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10757; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10758
10759 // Grab the consecutive column-span kids, and reparent them into a
10760 // block frame.
10761 RefPtr<ComputedStyle> columnSpanWrapperStyle =
10762 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
10763 PseudoStyleType::columnSpanWrapper);
10764 nsBlockFrame* columnSpanWrapper =
10765 NS_NewBlockFrame(mPresShell, columnSpanWrapperStyle);
10766 InitAndRestoreFrame(aState, content, parentFrame, columnSpanWrapper, false);
10767 columnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10768 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10769
10770 nsFrameList columnSpanKids =
10771 aChildList.Split([](nsIFrame* f) { return !f->IsColumnSpan(); });
10772 columnSpanKids.ApplySetParent(columnSpanWrapper);
10773 columnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10774 std::move(columnSpanKids));
10775 if (aPositionedFrame) {
10776 aState.ReparentAbsoluteItems(columnSpanWrapper);
10777 }
10778
10779 siblings.AppendFrame(nullptr, columnSpanWrapper);
10780
10781 // Grab the consecutive non-column-span kids, and reparent them into a new
10782 // continuation of the last non-column-span wrapper frame.
10783 auto* nonColumnSpanWrapper = static_cast<nsContainerFrame*>(
10784 CreateContinuingFrame(lastNonColumnSpanWrapper, parentFrame, false));
10785 nonColumnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10786 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10787 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"
, 10788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10788; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10788 "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"
, 10788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10788; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10789
10790 if (aChildList.NotEmpty()) {
10791 nsFrameList nonColumnSpanKids =
10792 aChildList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10793
10794 nonColumnSpanKids.ApplySetParent(nonColumnSpanWrapper);
10795 nonColumnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10796 std::move(nonColumnSpanKids));
10797 if (aPositionedFrame) {
10798 aState.ReparentAbsoluteItems(nonColumnSpanWrapper);
10799 }
10800 if (isInitialBlockFloatCB) {
10801 aState.ReparentFloats(nonColumnSpanWrapper);
10802 }
10803 }
10804
10805 siblings.AppendFrame(nullptr, nonColumnSpanWrapper);
10806
10807 lastNonColumnSpanWrapper = nonColumnSpanWrapper;
10808 } while (aChildList.NotEmpty());
10809
10810 // Unset the bit because the last non-column-span wrapper has no column-span
10811 // siblings.
10812 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(false);
10813
10814 return siblings;
10815}
10816
10817bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
10818 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
10819 nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
10820 if (!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10821 return false;
10822 }
10823
10824 if (aFrameList.IsEmpty()) {
10825 return false;
10826 }
10827
10828 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"
, 10830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10830
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10829 "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"
, 10830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10830
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10830 "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"
, 10830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10830
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
10831
10832 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
10833 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
10834 // We are appending a list of frames to the last continuation of a
10835 // ::-moz-column-content. This is the case where we can fix the frame tree
10836 // instead of reframing the containing block. Return false and let
10837 // AppendFramesToParent() deal with this.
10838 return false;
10839 }
10840
10841 auto HasColumnSpan = [](const nsFrameList& aList) {
10842 for (nsIFrame* f : aList) {
10843 if (f->IsColumnSpan()) {
10844 return true;
10845 }
10846 }
10847 return false;
10848 };
10849
10850 if (HasColumnSpan(aFrameList)) {
10851 // If any frame in the frame list has "column-span:all" style, i.e. a
10852 // -moz-column-span-wrapper frame, we need to reframe the multi-column
10853 // containing block.
10854 //
10855 // We can only be here if none of the new inserted nsIContent* nodes (via
10856 // ContentAppended or ContentRangeInserted) have column-span:all style, yet
10857 // some of them have column-span:all descendants. Sadly, there's no way to
10858 // detect this by checking FrameConstructionItems in WipeContainingBlock().
10859 // Otherwise, we would have already wiped the multi-column containing block.
10860 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)
10861 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)
;
10862
10863 // aFrameList can contain placeholder frames. In order to destroy their
10864 // associated out-of-flow frames properly, we need to manually flush all the
10865 // out-of-flow frames in aState to their container frames.
10866 aState.ProcessFrameInsertionsForAllLists();
10867 DestroyContext context(mPresShell);
10868 aFrameList.DestroyFrames(context);
10869 RecreateFramesForContent(
10870 GetMultiColumnContainingBlockFor(aParentFrame)->GetContent(),
10871 InsertionKind::Async);
10872 return true;
10873 }
10874
10875 return false;
10876}
10877
10878nsIFrame* nsCSSFrameConstructor::ConstructInline(
10879 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
10880 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
10881 nsFrameList& aFrameList) {
10882 // If an inline frame has non-inline kids, then we chop up the child list
10883 // into runs of blocks and runs of inlines, create anonymous block frames to
10884 // contain the runs of blocks, inline frames with our style for the runs of
10885 // inlines, and put all these frames, in order, into aFrameList.
10886 //
10887 // When there are column-span blocks in a run of blocks, instead of creating
10888 // an anonymous block to wrap them, we create multiple anonymous blocks,
10889 // wrapping runs of non-column-spans and runs of column-spans.
10890 //
10891 // We return the the first one. The whole setup is called an {ib}
10892 // split; in what follows "frames in the split" refers to the anonymous blocks
10893 // and inlines that contain our children.
10894 //
10895 // {ib} splits maintain the following invariants:
10896 // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
10897 // set.
10898 //
10899 // 2) Each frame in the split has the nsIFrame::IBSplitSibling
10900 // property pointing to the next frame in the split, except for the last
10901 // one, which does not have it set.
10902 //
10903 // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
10904 // property pointing to the previous frame in the split, except for the
10905 // first one, which does not have it set.
10906 //
10907 // 4) The first and last frame in the split are always inlines.
10908 //
10909 // 5) The frames wrapping runs of non-column-spans are linked together as
10910 // continuations. The frames wrapping runs of column-spans are *not*
10911 // linked with each other nor with other non-column-span wrappers.
10912 //
10913 // 6) The first and last frame in the chains of blocks are always wrapping
10914 // non-column-spans. Both of them are created even if they're empty.
10915 //
10916 // An invariant that is NOT maintained is that the wrappers are actually
10917 // linked via GetNextSibling linkage. A simple example is an inline
10918 // containing an inline that contains a block. The three parts of the inner
10919 // inline end up with three different parents.
10920 //
10921 // For example, this HTML:
10922 // <span>
10923 // <div>a</div>
10924 // <span>
10925 // b
10926 // <div>c</div>
10927 // </span>
10928 // d
10929 // <div>e</div>
10930 // f
10931 // </span>
10932 // Gives the following frame tree:
10933 //
10934 // Inline (outer span)
10935 // Block (anonymous, outer span)
10936 // Block (div)
10937 // Text("a")
10938 // Inline (outer span)
10939 // Inline (inner span)
10940 // Text("b")
10941 // Block (anonymous, outer span)
10942 // Block (anonymous, inner span)
10943 // Block (div)
10944 // Text("c")
10945 // Inline (outer span)
10946 // Inline (inner span)
10947 // Text("d")
10948 // Block (anonymous, outer span)
10949 // Block (div)
10950 // Text("e")
10951 // Inline (outer span)
10952 // Text("f")
10953
10954 nsIContent* const content = aItem.mContent;
10955 ComputedStyle* const computedStyle = aItem.mComputedStyle;
10956
10957 nsInlineFrame* newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
10958
10959 // Initialize the frame
10960 InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
10961
10962 // definition cannot be inside next block because the object's destructor is
10963 // significant. this is part of the fix for bug 42372
10964 nsFrameConstructorSaveState absoluteSaveState;
10965
10966 bool isAbsPosCB = newFrame->IsAbsPosContainingBlock();
10967 newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10968 if (isAbsPosCB) {
10969 // Relatively positioned frames becomes a container for child
10970 // frames that are positioned
10971 aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
10972 }
10973
10974 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10975 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10976 newFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10977 }
10978
10979 // Process the child content
10980 nsFrameList childList;
10981 ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
10982 /* aParentIsWrapperAnonBox = */ false, childList);
10983
10984 nsIFrame* firstBlock = nullptr;
10985 if (!aItem.mIsAllInline) {
10986 for (nsIFrame* f : childList) {
10987 if (f->IsBlockOutside()) {
10988 firstBlock = f;
10989 break;
10990 }
10991 }
10992 }
10993
10994 if (aItem.mIsAllInline || !firstBlock) {
10995 // This part is easy. We either already know we have no non-inline kids,
10996 // or haven't found any when constructing actual frames (the latter can
10997 // happen only if out-of-flows that we thought had no containing block
10998 // acquired one when ancestor inline frames and {ib} splits got
10999 // constructed). Just put all the kids into the single inline frame and
11000 // bail.
11001 newFrame->SetInitialChildList(FrameChildListID::Principal,
11002 std::move(childList));
11003 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
11004 return newFrame;
11005 }
11006
11007 // This inline frame contains several types of children. Therefore this frame
11008 // has to be chopped into several pieces, as described above.
11009
11010 // Grab the first inline's kids
11011 nsFrameList firstInlineKids = childList.TakeFramesBefore(firstBlock);
11012 newFrame->SetInitialChildList(FrameChildListID::Principal,
11013 std::move(firstInlineKids));
11014
11015 aFrameList.AppendFrame(nullptr, newFrame);
11016
11017 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
11018 CreateIBSiblings(aState, newFrame, isAbsPosCB, childList, aFrameList);
11019
11020 return newFrame;
11021}
11022
11023void nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
11024 nsContainerFrame* aInitialInline,
11025 bool aIsAbsPosCB,
11026 nsFrameList& aChildList,
11027 nsFrameList& aSiblings) {
11028 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"
, 11028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 11028; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11029
11030 nsIContent* content = aInitialInline->GetContent();
11031 ComputedStyle* computedStyle = aInitialInline->Style();
11032 nsContainerFrame* parentFrame = aInitialInline->GetParent();
11033
11034 // Resolve the right style for our anonymous blocks.
11035 //
11036 // The distinction in styles is needed because of CSS 2.1, section
11037 // 9.2.1.1, which says:
11038 //
11039 // When such an inline box is affected by relative positioning, any
11040 // resulting translation also affects the block-level box contained
11041 // in the inline box.
11042 RefPtr<ComputedStyle> blockSC =
11043 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
11044 PseudoStyleType::mozBlockInsideInlineWrapper, computedStyle);
11045
11046 nsContainerFrame* lastNewInline =
11047 static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
11048 do {
11049 // On entry to this loop aChildList is not empty and the first frame in it
11050 // is block-level.
11051 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"
, 11051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Should have child items" ")"); do { *((volatile int*)
__null) = 11051; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11052 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"
, 11053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11053; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11053 "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"
, 11053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11053; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11054
11055 // The initial run of blocks belongs to an anonymous block that we create
11056 // right now. The anonymous block will be the parent of these block
11057 // children of the inline.
11058 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
11059 InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
11060 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11061 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11062 }
11063
11064 // Find the first non-block child which defines the end of our block kids
11065 // and the start of our next inline's kids
11066 nsFrameList blockKids =
11067 aChildList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
11068
11069 if (!aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11070 MoveChildrenTo(aInitialInline, blockFrame, blockKids);
11071
11072 SetFrameIsIBSplit(lastNewInline, blockFrame);
11073 aSiblings.AppendFrame(nullptr, blockFrame);
11074 } else {
11075 // Extract any initial non-column-span frames, and put them in
11076 // blockFrame's child list.
11077 nsFrameList initialNonColumnSpanKids =
11078 blockKids.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
11079 MoveChildrenTo(aInitialInline, blockFrame, initialNonColumnSpanKids);
11080
11081 SetFrameIsIBSplit(lastNewInline, blockFrame);
11082 aSiblings.AppendFrame(nullptr, blockFrame);
11083
11084 if (blockKids.NotEmpty()) {
11085 // Although SetFrameIsIBSplit() will add NS_FRAME_PART_OF_IBSPLIT for
11086 // blockFrame later, we manually add the bit earlier here to make all
11087 // the continuations of blockFrame created in
11088 // CreateColumnSpanSiblings(), i.e. non-column-span wrappers, have the
11089 // bit via nsIFrame::Init().
11090 blockFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
11091
11092 nsFrameList columnSpanSiblings =
11093 CreateColumnSpanSiblings(aState, blockFrame, blockKids,
11094 aIsAbsPosCB ? aInitialInline : nullptr);
11095 aSiblings.AppendFrames(nullptr, std::move(columnSpanSiblings));
11096 }
11097 }
11098
11099 // Now grab the initial inlines in aChildList and put them into an inline
11100 // frame.
11101 nsInlineFrame* inlineFrame = NS_NewInlineFrame(mPresShell, computedStyle);
11102 InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
11103 inlineFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
11104 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11105 inlineFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11106 }
11107
11108 if (aIsAbsPosCB) {
11109 inlineFrame->MarkAsAbsoluteContainingBlock();
11110 }
11111
11112 if (aChildList.NotEmpty()) {
11113 nsFrameList inlineKids =
11114 aChildList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
11115 MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
11116 }
11117
11118 SetFrameIsIBSplit(blockFrame, inlineFrame);
11119 aSiblings.AppendFrame(nullptr, inlineFrame);
11120 lastNewInline = inlineFrame;
11121 } while (aChildList.NotEmpty());
11122
11123 SetFrameIsIBSplit(lastNewInline, nullptr);
11124}
11125
11126void nsCSSFrameConstructor::BuildInlineChildItems(
11127 nsFrameConstructorState& aState, FrameConstructionItem& aParentItem,
11128 bool aItemIsWithinSVGText, bool aItemAllowsTextPathChild) {
11129 ComputedStyle* const parentComputedStyle = aParentItem.mComputedStyle;
11130 nsIContent* const parentContent = aParentItem.mContent;
11131
11132 if (!aItemIsWithinSVGText) {
11133 if (parentComputedStyle->StyleDisplay()->IsListItem()) {
11134 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11135 *parentComputedStyle, PseudoStyleType::marker,
11136 aParentItem.mChildItems);
11137 }
11138 // Probe for generated content before
11139 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11140 *parentComputedStyle, PseudoStyleType::before,
11141 aParentItem.mChildItems);
11142 }
11143
11144 ItemFlags flags;
11145 if (aItemIsWithinSVGText) {
11146 flags += ItemFlag::IsWithinSVGText;
11147 }
11148 if (aItemAllowsTextPathChild &&
11149 aParentItem.mContent->IsSVGElement(nsGkAtoms::a)) {
11150 flags += ItemFlag::AllowTextPathChild;
11151 }
11152
11153 FlattenedChildIterator iter(parentContent);
11154 for (nsIContent* content = iter.GetNextChild(); content;
11155 content = iter.GetNextChild()) {
11156 AddFrameConstructionItems(aState, content, iter.ShadowDOMInvolved(),
11157 *parentComputedStyle, InsertionPoint(),
11158 aParentItem.mChildItems, flags);
11159 }
11160
11161 if (!aItemIsWithinSVGText) {
11162 // Probe for generated content after
11163 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11164 *parentComputedStyle, PseudoStyleType::after,
11165 aParentItem.mChildItems);
11166 }
11167
11168 aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
11169}
11170
11171// return whether it's ok to append (in the AppendFrames sense) to
11172// aParentFrame if our nextSibling is aNextSibling. aParentFrame must
11173// be an ib-split inline.
11174static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
11175 nsIFrame* aNextSibling) {
11176 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"
, 11176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInlineFrame(aParentFrame)"
") (" "Must have an inline parent here" ")"); do { *((volatile
int*)__null) = 11176; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11177
11178 do {
11179 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"
, 11180); MOZ_PretendNoReturn(); } } while (0)
11180 "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"
, 11180); MOZ_PretendNoReturn(); } } while (0)
;
11181 if (aNextSibling || aParentFrame->GetNextContinuation() ||
11182 GetIBSplitSibling(aParentFrame)) {
11183 return false;
11184 }
11185
11186 aNextSibling = aParentFrame->GetNextSibling();
11187 aParentFrame = aParentFrame->GetParent();
11188 } while (IsInlineFrame(aParentFrame));
11189
11190 return true;
11191}
11192
11193bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
11194#define TRACE(reason) \
11195 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)
11196 "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)
;
11197
11198 const LayoutFrameType frameType = aFrame->Type();
11199
11200 // FIXME(emilio): This looks terribly inefficient if you insert elements deep
11201 // in a MathML subtree.
11202 if (aFrame->IsMathMLFrame()) {
11203 TRACE("MathML");
11204 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11205 return true;
11206 }
11207
11208 // A ruby-related frame that's getting new children.
11209 // The situation for ruby is complex, especially when interacting with
11210 // spaces. It contains these two special cases apart from tables:
11211 // 1) There are effectively three types of white spaces in ruby frames
11212 // we handle differently: leading/tailing/inter-level space,
11213 // inter-base/inter-annotation space, and inter-segment space.
11214 // These three types of spaces can be converted to each other when
11215 // their sibling changes.
11216 // 2) The first effective child of a ruby frame must always be a ruby
11217 // base container. It should be created or destroyed accordingly.
11218 if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
11219 RubyUtils::IsRubyContainerBox(frameType)) {
11220 // We want to optimize it better, and avoid reframing as much as
11221 // possible. But given the cases above, and the fact that a ruby
11222 // usually won't be very large, it should be fine to reframe it.
11223 TRACE("Ruby");
11224 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11225 return true;
11226 }
11227
11228 // Reframe the multi-column container whenever elements insert/append
11229 // into it because we need to reconstruct column-span split.
11230 if (aFrame->IsColumnSetWrapperFrame()) {
11231 TRACE("Multi-column");
11232 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11233 return true;
11234 }
11235
11236 return false;
11237
11238#undef TRACE
11239}
11240
11241bool nsCSSFrameConstructor::WipeContainingBlock(
11242 nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
11243 nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
11244 nsIFrame* aPrevSibling) {
11245#define TRACE(reason) \
11246 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)
11247 "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)
;
11248
11249 if (aItems.IsEmpty()) {
11250 return false;
11251 }
11252
11253 // Before we go and append the frames, we must check for several
11254 // special situations.
11255
11256 if (aFrame->GetContent() == mDocument->GetRootElement()) {
11257 // Situation #1 is when we insert content that becomes the canonical body
11258 // element, and its used WritingMode is different from the root element's
11259 // used WritingMode.
11260 // We need to reframe the root element so that the root element's frames has
11261 // the correct writing-mode propagated from body element. (See
11262 // nsCSSFrameConstructor::ConstructDocElementFrame.)
11263 //
11264 // Bug 1594297: When inserting a new <body>, we may need to reframe the old
11265 // <body> which has a "overflow" value other than simple "visible". But it's
11266 // tricky, see bug 1593752.
11267 nsIContent* bodyElement = mDocument->GetBodyElement();
11268 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11269 const WritingMode bodyWM(iter.item().mComputedStyle);
11270 if (iter.item().mContent == bodyElement &&
11271 bodyWM != aFrame->GetWritingMode()) {
11272 TRACE("Root");
11273 RecreateFramesForContent(mDocument->GetRootElement(),
11274 InsertionKind::Async);
11275 return true;
11276 }
11277 }
11278 }
11279
11280 nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
11281
11282 // Situation #2 is a flex / grid container frame into which we're inserting
11283 // new inline non-replaced children, adjacent to an existing anonymous flex or
11284 // grid item.
11285 if (aFrame->IsFlexOrGridContainer()) {
11286 FCItemIterator iter(aItems);
11287
11288 // Check if we're adding to-be-wrapped content right *after* an existing
11289 // anonymous flex or grid item (which would need to absorb this content).
11290 const bool isLegacyWebKitBox = IsFlexContainerForLegacyWebKitBox(aFrame);
11291 if (aPrevSibling && IsAnonymousItem(aPrevSibling) &&
11292 iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11293 TRACE("Inserting inline after anon flex or grid item");
11294 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11295 return true;
11296 }
11297
11298 // Check if we're adding to-be-wrapped content right *before* an existing
11299 // anonymous flex or grid item (which would need to absorb this content).
11300 if (nextSibling && IsAnonymousItem(nextSibling)) {
11301 // Jump to the last entry in the list
11302 iter.SetToEnd();
11303 iter.Prev();
11304 if (iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11305 TRACE("Inserting inline before anon flex or grid item");
11306 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11307 return true;
11308 }
11309 }
11310 }
11311
11312 // Situation #3 is an anonymous flex or grid item that's getting new children
11313 // who don't want to be wrapped.
11314 if (IsAnonymousItem(aFrame)) {
11315 AssertAnonymousFlexOrGridItemParent(aFrame, aFrame->GetParent());
11316
11317 // We need to push a null float containing block to be sure that
11318 // "NeedsAnonFlexOrGridItem" will know we're not honoring floats for this
11319 // inserted content. (In particular, this is necessary in order for
11320 // its "GetGeometricParent" call to return the correct result.)
11321 // We're not honoring floats on this content because it has the
11322 // _flex/grid container_ as its parent in the content tree.
11323 nsFrameConstructorSaveState floatSaveState;
11324 aState.PushFloatContainingBlock(nullptr, floatSaveState);
11325
11326 FCItemIterator iter(aItems);
11327 // Skip over things that _do_ need an anonymous flex item, because
11328 // they're perfectly happy to go here -- they won't cause a reframe.
11329 nsIFrame* containerFrame = aFrame->GetParent();
11330 const bool isLegacyWebKitBox =
11331 IsFlexContainerForLegacyWebKitBox(containerFrame);
11332 if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11333 // We hit something that _doesn't_ need an anonymous flex item!
11334 // Rebuild the flex container to bust it out.
11335 TRACE("Inserting non-inlines inside anon flex or grid item");
11336 RecreateFramesForContent(containerFrame->GetContent(),
11337 InsertionKind::Async);
11338 return true;
11339 }
11340
11341 // If we get here, then everything in |aItems| needs to be wrapped in
11342 // an anonymous flex or grid item. That's where it's already going - good!
11343 }
11344
11345 // Situation #4 is a case when table pseudo-frames don't work out right
11346 ParentType parentType = GetParentType(aFrame);
11347 // If all the kids want a parent of the type that aFrame is, then we're all
11348 // set to go. Indeed, there won't be any table pseudo-frames created between
11349 // aFrame and the kids, so those won't need to be merged with any table
11350 // pseudo-frames that might already be kids of aFrame. If aFrame itself is a
11351 // table pseudo-frame, then all the kids in this list would have wanted a
11352 // frame of that type wrapping them anyway, so putting them inside it is ok.
11353 if (!aItems.AllWantParentType(parentType)) {
11354 // Don't give up yet. If parentType is not eTypeBlock and the parent is
11355 // not a generated content frame, then try filtering whitespace out of the
11356 // list.
11357 if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
11358 // For leading whitespace followed by a kid that wants our parent type,
11359 // there are four cases:
11360 // 1) We have a previous sibling which is not a table pseudo. That means
11361 // that previous sibling wanted a (non-block) parent of the type we're
11362 // looking at. Then the whitespace comes between two table-internal
11363 // elements, so should be collapsed out.
11364 // 2) We have a previous sibling which is a table pseudo. It might have
11365 // kids who want this whitespace, so we need to reframe.
11366 // 3) We have no previous sibling and our parent frame is not a table
11367 // pseudo. That means that we'll be at the beginning of our actual
11368 // non-block-type parent, and the whitespace is OK to collapse out.
11369 // If something is ever inserted before us, it'll find our own parent
11370 // as its parent and if it's something that would care about the
11371 // whitespace it'll want a block parent, so it'll trigger a reframe at
11372 // that point.
11373 // 4) We have no previous sibling and our parent frame is a table pseudo.
11374 // Need to reframe.
11375 // All that is predicated on finding the correct previous sibling. We
11376 // might have to walk backwards along continuations from aFrame to do so.
11377 //
11378 // It's always OK to drop whitespace between any two items that want a
11379 // parent of type parentType.
11380 //
11381 // For trailing whitespace preceded by a kid that wants our parent type,
11382 // there are four cases:
11383 // 1) We have a next sibling which is not a table pseudo. That means
11384 // that next sibling wanted a (non-block) parent of the type we're
11385 // looking at. Then the whitespace comes between two table-internal
11386 // elements, so should be collapsed out.
11387 // 2) We have a next sibling which is a table pseudo. It might have
11388 // kids who want this whitespace, so we need to reframe.
11389 // 3) We have no next sibling and our parent frame is not a table
11390 // pseudo. That means that we'll be at the end of our actual
11391 // non-block-type parent, and the whitespace is OK to collapse out.
11392 // If something is ever inserted after us, it'll find our own parent
11393 // as its parent and if it's something that would care about the
11394 // whitespace it'll want a block parent, so it'll trigger a reframe at
11395 // that point.
11396 // 4) We have no next sibling and our parent frame is a table pseudo.
11397 // Need to reframe.
11398 // All that is predicated on finding the correct next sibling. We might
11399 // have to walk forward along continuations from aFrame to do so. That
11400 // said, in the case when nextSibling is null at this point and aIsAppend
11401 // is true, we know we're in case 3. Furthermore, in that case we don't
11402 // even have to worry about the table pseudo situation; we know our
11403 // parent is not a table pseudo there.
11404 FCItemIterator iter(aItems);
11405 FCItemIterator start(iter);
11406 do {
11407 if (iter.SkipItemsWantingParentType(parentType)) {
11408 break;
11409 }
11410
11411 // iter points to an item that wants a different parent. If it's not
11412 // whitespace, we're done; no more point scanning the list.
11413 if (!iter.item().IsWhitespace(aState)) {
11414 break;
11415 }
11416
11417 if (iter == start) {
11418 // Leading whitespace. How to handle this depends on our
11419 // previous sibling and aFrame. See the long comment above.
11420 nsIFrame* prevSibling = aPrevSibling;
11421 if (!prevSibling) {
11422 // Try to find one after all
11423 nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
11424 while (parentPrevCont) {
11425 prevSibling = parentPrevCont->PrincipalChildList().LastChild();
11426 if (prevSibling) {
11427 break;
11428 }
11429 parentPrevCont = parentPrevCont->GetPrevContinuation();
11430 }
11431 };
11432 if (prevSibling) {
11433 if (IsTablePseudo(prevSibling)) {
11434 // need to reframe
11435 break;
11436 }
11437 } else if (IsTablePseudo(aFrame)) {
11438 // need to reframe
11439 break;
11440 }
11441 }
11442
11443 FCItemIterator spaceEndIter(iter);
11444 // Advance spaceEndIter past any whitespace
11445 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
11446
11447 bool okToDrop;
11448 if (trailingSpaces) {
11449 // Trailing whitespace. How to handle this depeds on aIsAppend, our
11450 // next sibling and aFrame. See the long comment above.
11451 okToDrop = aIsAppend && !nextSibling;
11452 if (!okToDrop) {
11453 if (!nextSibling) {
11454 // Try to find one after all
11455 nsIFrame* parentNextCont = aFrame->GetNextContinuation();
11456 while (parentNextCont) {
11457 nextSibling = parentNextCont->PrincipalChildList().FirstChild();
11458 if (nextSibling) {
11459 break;
11460 }
11461 parentNextCont = parentNextCont->GetNextContinuation();
11462 }
11463 }
11464
11465 okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
11466 (!nextSibling && !IsTablePseudo(aFrame));
11467 }
11468#ifdef DEBUG1
11469 else {
11470 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"
, 11470); MOZ_PretendNoReturn(); } } while (0)
;
11471 }
11472#endif
11473 } else {
11474 okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
11475 }
11476
11477 if (okToDrop) {
11478 iter.DeleteItemsTo(this, spaceEndIter);
11479 } else {
11480 // We're done: we don't want to drop the whitespace, and it has the
11481 // wrong parent type.
11482 break;
11483 }
11484
11485 // Now loop, since |iter| points to item right after the whitespace we
11486 // removed.
11487 } while (!iter.IsDone());
11488 }
11489
11490 // We might be able to figure out some sort of optimizations here, but they
11491 // would have to depend on having a correct aPrevSibling and a correct next
11492 // sibling. For example, we can probably avoid reframing if none of
11493 // aFrame, aPrevSibling, and next sibling are table pseudo-frames. But it
11494 // doesn't seem worth it to worry about that for now, especially since we
11495 // in fact do not have a reliable aPrevSibling, nor any next sibling, in
11496 // this method.
11497
11498 // aItems might have changed, so recheck the parent type thing. In fact,
11499 // it might be empty, so recheck that too.
11500 if (aItems.IsEmpty()) {
11501 return false;
11502 }
11503
11504 // If aFrame is empty, the insertion process will be able to take care of
11505 // creating any needed pseudo-parents.
11506 if (!aItems.AllWantParentType(parentType) &&
11507 !SafeToInsertPseudoNeedingChildren(aFrame)) {
11508 // Reframing aFrame->GetContent() is good enough, since the content of
11509 // table pseudo-frames is the ancestor content.
11510 TRACE("Pseudo-frames going wrong");
11511 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11512 return true;
11513 }
11514 }
11515
11516 // Situation #5 is a frame in multicol subtree that's getting new children.
11517 if (aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11518 bool anyColumnSpanItems = false;
11519 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11520 if (iter.item().mComputedStyle->StyleColumn()->IsColumnSpanStyle()) {
11521 anyColumnSpanItems = true;
11522 break;
11523 }
11524 }
11525
11526 bool needsReframe =
11527 // 1. Insert / append any column-span children.
11528 anyColumnSpanItems ||
11529 // 2. GetInsertionPrevSibling() modifies insertion parent. If the prev
11530 // sibling is a column-span, aFrame ends up being the
11531 // column-span-wrapper.
11532 aFrame->Style()->GetPseudoType() ==
11533 PseudoStyleType::columnSpanWrapper ||
11534 // 3. Append into {ib} split container. There might be room for
11535 // optimization, but let's reframe for correctness...
11536 IsFramePartOfIBSplit(aFrame);
11537
11538 if (needsReframe) {
11539 TRACE("Multi-column");
11540 RecreateFramesForContent(
11541 GetMultiColumnContainingBlockFor(aFrame)->GetContent(),
11542 InsertionKind::Async);
11543 return true;
11544 }
11545
11546 // If we get here, then we need further check for {ib} split to decide
11547 // whether to reframe. For example, appending a block into an empty inline
11548 // that is not part of an {ib} split, but should become an {ib} split.
11549 }
11550
11551 // A <fieldset> may need to pick up a new rendered legend from aItems.
11552 // We currently can't handle this case without recreating frames for
11553 // the fieldset.
11554 // XXXmats we should be able to optimize this when the fieldset doesn't
11555 // currently have a rendered legend. ContentRangeInserted needs to be fixed
11556 // to use the inner frame as the content insertion frame in that case.
11557 if (const auto* fieldset = GetFieldSetFrameFor(aFrame)) {
11558 // Check if any item is eligible to be a rendered legend.
11559 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11560 const auto& item = iter.item();
11561 if (!item.mContent->IsHTMLElement(nsGkAtoms::legend)) {
11562 continue;
11563 }
11564 const auto* display = item.mComputedStyle->StyleDisplay();
11565 if (display->IsFloatingStyle() ||
11566 display->IsAbsolutelyPositionedStyle()) {
11567 continue;
11568 }
11569 TRACE("Fieldset with rendered legend");
11570 RecreateFramesForContent(fieldset->GetContent(), InsertionKind::Async);
11571 return true;
11572 }
11573 }
11574
11575 // Now we have several cases involving {ib} splits. Put them all in a
11576 // do/while with breaks to take us to the "go and reconstruct" code.
11577 do {
11578 if (IsInlineFrame(aFrame)) {
11579 if (aItems.AreAllItemsInline()) {
11580 // We can just put the kids in.
11581 return false;
11582 }
11583
11584 if (!IsFramePartOfIBSplit(aFrame)) {
11585 // Need to go ahead and reconstruct.
11586 break;
11587 }
11588
11589 // Now we're adding kids including some blocks to an inline part of an
11590 // {ib} split. If we plan to call AppendFrames, and don't have a next
11591 // sibling for the new frames, and our parent is the last continuation of
11592 // the last part of the {ib} split, and the same is true of all our
11593 // ancestor inlines (they have no following continuations and they're the
11594 // last part of their {ib} splits and we'd be adding to the end for all
11595 // of them), then AppendFrames will handle things for us. Bail out in
11596 // that case.
11597 if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
11598 return false;
11599 }
11600
11601 // Need to reconstruct.
11602 break;
11603 }
11604
11605 // Now we know we have a block parent. If it's not part of an
11606 // ib-split, we're all set.
11607 if (!IsFramePartOfIBSplit(aFrame)) {
11608 return false;
11609 }
11610
11611 // We're adding some kids to a block part of an {ib} split. If all the
11612 // kids are blocks, we don't need to reconstruct.
11613 if (aItems.AreAllItemsBlock()) {
11614 return false;
11615 }
11616
11617 // We might have some inline kids for this block. Just fall out of the
11618 // loop and reconstruct.
11619 } while (false);
11620
11621 // If we don't have a containing block, start with aFrame and look for one.
11622 if (!aContainingBlock) {
11623 aContainingBlock = aFrame;
11624 }
11625
11626 // To find the right block to reframe, just walk up the tree until we find a
11627 // frame that is:
11628 // 1) Not part of an IB split
11629 // 2) Not a pseudo-frame
11630 // 3) Not an inline frame
11631 // We're guaranteed to find one, since ComputedStyle::ApplyStyleFixups
11632 // enforces that the root is display:none, display:table, or display:block.
11633 // Note that walking up "too far" is OK in terms of correctness, even if it
11634 // might be a little inefficient. This is why we walk out of all
11635 // pseudo-frames -- telling which ones are or are not OK to walk out of is
11636 // too hard (and I suspect that we do in fact need to walk out of all of
11637 // them).
11638 while (IsFramePartOfIBSplit(aContainingBlock) ||
11639 aContainingBlock->IsInlineOutside() ||
11640 aContainingBlock->Style()->IsPseudoOrAnonBox()) {
11641 aContainingBlock = aContainingBlock->GetParent();
11642 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"
, 11644); MOZ_PretendNoReturn(); } } while (0)
11643 "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"
, 11644); MOZ_PretendNoReturn(); } } while (0)
11644 "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"
, 11644); MOZ_PretendNoReturn(); } } while (0)
;
11645 }
11646
11647 // Tell parent of the containing block to reformulate the
11648 // entire block. This is painful and definitely not optimal
11649 // but it will *always* get the right answer.
11650
11651 nsIContent* blockContent = aContainingBlock->GetContent();
11652 TRACE("IB splits");
11653 RecreateFramesForContent(blockContent, InsertionKind::Async);
11654 return true;
11655#undef TRACE
11656}
11657
11658void nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame) {
11659 // XXXbz how exactly would we get here while isReflowing anyway? Should this
11660 // whole test be ifdef DEBUG?
11661 if (mPresShell->IsReflowLocked()) {
11662 // don't ReframeContainingBlock, this will result in a crash
11663 // if we remove a tree that's in reflow - see bug 121368 for testcase
11664 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"
, 11666); MOZ_PretendNoReturn(); } while (0)
11665 "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"
, 11666); MOZ_PretendNoReturn(); } while (0)
11666 "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"
, 11666); MOZ_PretendNoReturn(); } while (0)
;
11667 return;
11668 }
11669
11670 // Get the first "normal" ancestor of the target frame.
11671 nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
11672 if (containingBlock) {
11673 // From here we look for the containing block in case the target
11674 // frame is already a block (which can happen when an inline frame
11675 // wraps some of its content in an anonymous block; see
11676 // ConstructInline)
11677
11678 // NOTE: We used to get the FloatContainingBlock here, but it was often
11679 // wrong. GetIBContainingBlock works much better and provides the correct
11680 // container in all cases so GetFloatContainingBlock(aFrame) has been
11681 // removed
11682
11683 // And get the containingBlock's content
11684 if (nsIContent* blockContent = containingBlock->GetContent()) {
11685#ifdef DEBUG1
11686 if (gNoisyContentUpdates) {
11687 printf(" ==> blockContent=%p\n", blockContent);
11688 }
11689#endif
11690 RecreateFramesForContent(blockContent, InsertionKind::Async);
11691 return;
11692 }
11693 }
11694
11695 // If we get here, we're screwed!
11696 RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
11697 InsertionKind::Async);
11698}
11699
11700//////////////////////////////////////////////////////////
11701// nsCSSFrameConstructor::FrameConstructionItem methods //
11702//////////////////////////////////////////////////////////
11703bool nsCSSFrameConstructor::FrameConstructionItem::IsWhitespace(
11704 nsFrameConstructorState& aState) const {
11705 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"
, 11706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11706; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
11706 "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"
, 11706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11706; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11707 if (!mIsText) {
11708 return false;
11709 }
11710 mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
11711 NS_REFRAME_IF_WHITESPACE);
11712 return mContent->TextIsOnlyWhitespace();
11713}
11714
11715//////////////////////////////////////////////////////////////
11716// nsCSSFrameConstructor::FrameConstructionItemList methods //
11717//////////////////////////////////////////////////////////////
11718void nsCSSFrameConstructor::FrameConstructionItemList::AdjustCountsForItem(
11719 FrameConstructionItem* aItem, int32_t aDelta) {
11720 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"
, 11720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDelta == 1 || aDelta == -1"
") (" "Unexpected delta" ")"); do { *((volatile int*)__null)
= 11720; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
11721 mItemCount += aDelta;
11722 if (aItem->mIsAllInline) {
11723 mInlineCount += aDelta;
11724 }
11725 if (aItem->mIsBlock) {
11726 mBlockCount += aDelta;
11727 }
11728 mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
11729}
11730
11731////////////////////////////////////////////////////////////////////////
11732// nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
11733////////////////////////////////////////////////////////////////////////
11734inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11735 SkipItemsWantingParentType(ParentType aParentType) {
11736 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"
, 11736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11736; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11737 while (item().DesiredParentType() == aParentType) {
11738 Next();
11739 if (IsDone()) {
11740 return true;
11741 }
11742 }
11743 return false;
11744}
11745
11746inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11747 SkipItemsNotWantingParentType(ParentType aParentType) {
11748 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"
, 11748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11748; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11749 while (item().DesiredParentType() != aParentType) {
11750 Next();
11751 if (IsDone()) {
11752 return true;
11753 }
11754 }
11755 return false;
11756}
11757
11758// Note: we implement -webkit-{inline-}box using nsFlexContainerFrame, but we
11759// use different rules for what gets wrapped in an anonymous flex item.
11760bool nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem(
11761 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11762 if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) {
11763 // This will be an inline non-replaced box.
11764 return true;
11765 }
11766
11767 if (aIsLegacyWebKitBox) {
11768 if (mComputedStyle->StyleDisplay()->IsInlineOutsideStyle()) {
11769 // In an emulated legacy box, all inline-level content gets wrapped in an
11770 // anonymous flex item.
11771 return true;
11772 }
11773 if (mIsPopup ||
11774 (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
11775 aState.GetGeometricParent(*mComputedStyle->StyleDisplay(), nullptr))) {
11776 // We're abspos or fixedpos (or a XUL popup), which means we'll spawn a
11777 // placeholder which (because our container is an emulated legacy box)
11778 // we'll need to wrap in an anonymous flex item. So, we just treat
11779 // _this_ frame as if _it_ needs to be wrapped in an anonymous flex item,
11780 // and then when we spawn the placeholder, it'll end up in the right
11781 // spot.
11782 return true;
11783 }
11784 }
11785
11786 return false;
11787}
11788
11789inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11790 SkipItemsThatNeedAnonFlexOrGridItem(const nsFrameConstructorState& aState,
11791 bool aIsLegacyWebKitBox) {
11792 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"
, 11792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11792; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11793 while (item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox)) {
11794 Next();
11795 if (IsDone()) {
11796 return true;
11797 }
11798 }
11799 return false;
11800}
11801
11802inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11803 SkipItemsThatDontNeedAnonFlexOrGridItem(
11804 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11805 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"
, 11805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11805; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11806 while (!(item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox))) {
11807 Next();
11808 if (IsDone()) {
11809 return true;
11810 }
11811 }
11812 return false;
11813}
11814
11815inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11816 SkipItemsNotWantingRubyParent() {
11817 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"
, 11817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11817; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11818 while (!IsRubyParentType(item().DesiredParentType())) {
11819 Next();
11820 if (IsDone()) {
11821 return true;
11822 }
11823 }
11824 return false;
11825}
11826
11827inline bool
11828nsCSSFrameConstructor::FrameConstructionItemList::Iterator::SkipWhitespace(
11829 nsFrameConstructorState& aState) {
11830 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"
, 11830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11830; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11831 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"
, 11831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "item().IsWhitespace(aState)"
") (" "Not pointing to whitespace?" ")"); do { *((volatile int
*)__null) = 11831; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11832 do {
11833 Next();
11834 if (IsDone()) {
11835 return true;
11836 }
11837 } while (item().IsWhitespace(aState));
11838
11839 return false;
11840}
11841
11842void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11843 AppendItemToList(FrameConstructionItemList& aTargetList) {
11844 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"
, 11844); MOZ_PretendNoReturn(); } } while (0)
;
11845 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"
, 11845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "should not be done" ")"); do { *((volatile int*)__null
) = 11845; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11846
11847 FrameConstructionItem* item = mCurrent;
11848 Next();
11849 item->remove();
11850 aTargetList.mItems.insertBack(item);
11851
11852 mList.AdjustCountsForItem(item, -1);
11853 aTargetList.AdjustCountsForItem(item, 1);
11854}
11855
11856void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11857 AppendItemsToList(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd,
11858 FrameConstructionItemList& aTargetList) {
11859 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"
, 11859); MOZ_PretendNoReturn(); } } while (0)
;
11860 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"
, 11860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11860; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11861
11862 // We can't just move our guts to the other list if it already has
11863 // some information or if we're not moving our entire list.
11864 if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
11865 do {
11866 AppendItemToList(aTargetList);
11867 } while (*this != aEnd);
11868 return;
11869 }
11870
11871 // Move our entire list of items into the empty target list.
11872 aTargetList.mItems = std::move(mList.mItems);
11873
11874 // Copy over the various counters
11875 aTargetList.mInlineCount = mList.mInlineCount;
11876 aTargetList.mBlockCount = mList.mBlockCount;
11877 aTargetList.mItemCount = mList.mItemCount;
11878 memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
11879 sizeof(aTargetList.mDesiredParentCounts));
11880
11881 // reset mList
11882 mList.Reset(aFCtor);
11883
11884 // Point ourselves to aEnd, as advertised
11885 SetToEnd();
11886 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"
, 11886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this == aEnd"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11886; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11887}
11888
11889void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::InsertItem(
11890 FrameConstructionItem* aItem) {
11891 if (IsDone()) {
11892 mList.mItems.insertBack(aItem);
11893 } else {
11894 // Just insert the item before us. There's no magic here.
11895 mCurrent->setPrevious(aItem);
11896 }
11897 mList.AdjustCountsForItem(aItem, 1);
11898
11899 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"
, 11899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem->getNext() == mCurrent"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11899; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11900}
11901
11902void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::DeleteItemsTo(
11903 nsCSSFrameConstructor* aFCtor, const Iterator& aEnd) {
11904 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"
, 11904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11904; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11905 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"
, 11905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this != aEnd"
") (" "Shouldn't be at aEnd yet" ")"); do { *((volatile int*
)__null) = 11905; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11906
11907 do {
11908 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"
, 11908); MOZ_PretendNoReturn(); } } while (0)
;
11909 FrameConstructionItem* item = mCurrent;
11910 Next();
11911 item->remove();
11912 mList.AdjustCountsForItem(item, -1);
11913 item->Delete(aFCtor);
11914 } while (*this != aEnd);
11915}
11916
11917void nsCSSFrameConstructor::QuotesDirty() {
11918 mQuotesDirty = true;
11919 mPresShell->SetNeedLayoutFlush();
11920}
11921
11922void nsCSSFrameConstructor::CountersDirty() {
11923 mCountersDirty = true;
11924 mPresShell->SetNeedLayoutFlush();
11925}
11926
11927void* nsCSSFrameConstructor::AllocateFCItem() {
11928 void* item;
11929 if (mFirstFreeFCItem) {
11930 item = mFirstFreeFCItem;
11931 mFirstFreeFCItem = mFirstFreeFCItem->mNext;
11932 } else {
11933 item = mFCItemPool.Allocate(sizeof(FrameConstructionItem));
11934 }
11935 ++mFCItemsInUse;
11936 return item;
11937}
11938
11939void nsCSSFrameConstructor::FreeFCItem(FrameConstructionItem* aItem) {
11940 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"
, 11940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFCItemsInUse != 0"
")"); do { *((volatile int*)__null) = 11940; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11941 if (--mFCItemsInUse == 0) {
11942 // The arena is now unused - clear it but retain one chunk.
11943 mFirstFreeFCItem = nullptr;
11944 mFCItemPool.Clear();
11945 } else {
11946 // Prepend it to the list of free items.
11947 FreeFCItemLink* item = reinterpret_cast<FreeFCItemLink*>(aItem);
11948 item->mNext = mFirstFreeFCItem;
11949 mFirstFreeFCItem = item;
11950 }
11951}
11952
11953void nsCSSFrameConstructor::AddSizeOfIncludingThis(
11954 nsWindowSizes& aSizes) const {
11955 if (nsIFrame* rootFrame = GetRootFrame()) {
11956 rootFrame->AddSizeOfExcludingThisForTree(aSizes);
11957 if (RetainedDisplayListBuilder* builder =
11958 rootFrame->GetProperty(RetainedDisplayListBuilder::Cached())) {
11959 builder->AddSizeOfIncludingThis(aSizes);
11960 }
11961 }
11962
11963 // This must be done after measuring from the frame tree, since frame
11964 // manager will measure sizes of staled computed values and style
11965 // structs, which only make sense after we know what are being used.
11966 nsFrameManager::AddSizeOfIncludingThis(aSizes);
11967
11968 // Measurement of the following members may be added later if DMD finds it
11969 // is worthwhile:
11970 // - mFCItemPool
11971 // - mContainStyleScopeManager
11972}