Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/base/nsCSSFrameConstructor.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef nsCSSFrameConstructor_h___
13
#define nsCSSFrameConstructor_h___
14
15
#include "mozilla/ArenaAllocator.h"
16
#include "mozilla/Attributes.h"
17
#include "mozilla/LinkedList.h"
18
#include "mozilla/Maybe.h"
19
#include "mozilla/RestyleManager.h"
20
#include "mozilla/ScrollStyles.h"
21
22
#include "nsCOMPtr.h"
23
#include "nsILayoutHistoryState.h"
24
#include "nsQuoteList.h"
25
#include "nsCounterManager.h"
26
#include "nsIAnonymousContentCreator.h"
27
#include "nsFrameManager.h"
28
29
struct nsFrameItems;
30
struct nsStyleDisplay;
31
struct nsGenConInitializer;
32
33
class nsContainerFrame;
34
class nsFirstLineFrame;
35
class nsFirstLetterFrame;
36
class nsICSSAnonBoxPseudo;
37
class nsIDocument;
38
class nsPageContentFrame;
39
struct PendingBinding;
40
41
class nsFrameConstructorState;
42
43
namespace mozilla {
44
45
class ComputedStyle;
46
47
namespace dom {
48
49
class CharacterData;
50
class Text;
51
class FlattenedChildIterator;
52
53
} // namespace dom
54
} // namespace mozilla
55
56
class nsCSSFrameConstructor final : public nsFrameManager
57
{
58
public:
59
  typedef mozilla::ComputedStyle ComputedStyle;
60
  typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
61
  typedef mozilla::dom::Element Element;
62
  typedef mozilla::dom::Text Text;
63
64
  // FIXME(emilio): Is this really needed?
65
  friend class mozilla::RestyleManager;
66
67
  nsCSSFrameConstructor(nsIDocument* aDocument, nsIPresShell* aPresShell);
68
0
  ~nsCSSFrameConstructor() {
69
0
    MOZ_ASSERT(mFCItemsInUse == 0);
70
0
  }
71
72
  // get the alternate text for a content node
73
  static void GetAlternateTextFor(Element* aContent,
74
                                  nsAtom* aTag,  // content object's tag
75
                                  nsAString& aAltText);
76
77
private:
78
  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) = delete;
79
  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) = delete;
80
81
public:
82
  /**
83
   * Whether insertion should be done synchronously or asynchronously.
84
   *
85
   * Generally, insertion is synchronous if we're entering frame construction
86
   * from restyle processing, and async if we're removing stuff, or need to
87
   * reconstruct some ancestor.
88
   *
89
   * Note that constructing async from frame construction will post a restyle
90
   * event, but won't need another whole refresh driver tick to go in. Instead
91
   * change hint processing will keep going as long as there are changes in the
92
   * queue.
93
   */
94
  enum class InsertionKind
95
  {
96
    Sync,
97
    Async,
98
  };
99
100
  mozilla::RestyleManager* RestyleManager() const
101
0
    { return mPresShell->GetPresContext()->RestyleManager(); }
102
103
  nsIFrame* ConstructRootFrame();
104
105
  void ReconstructDocElementHierarchy(InsertionKind);
106
107
108
private:
109
110
111
  enum Operation {
112
    CONTENTAPPEND,
113
    CONTENTINSERT
114
  };
115
116
  // aChild is the child being inserted for inserts, and the first
117
  // child being appended for appends.
118
  bool MaybeConstructLazily(Operation aOperation, nsIContent* aChild);
119
120
#ifdef DEBUG
121
  void CheckBitsForLazyFrameConstruction(nsIContent* aParent);
122
#else
123
0
  void CheckBitsForLazyFrameConstruction(nsIContent*) {}
124
#endif
125
126
  // Issues a single ContentInserted for each child in the range
127
  // [aStartChild, aEndChild).
128
  void IssueSingleInsertNofications(nsIContent* aStartChild,
129
                                    nsIContent* aEndChild,
130
                                    InsertionKind);
131
132
  /**
133
   * Data that represents an insertion point for some child content.
134
   */
135
  struct InsertionPoint
136
  {
137
    InsertionPoint()
138
      : mParentFrame(nullptr)
139
      , mContainer(nullptr)
140
0
    {}
141
142
    InsertionPoint(nsContainerFrame* aParentFrame, nsIContent* aContainer)
143
      : mParentFrame(aParentFrame)
144
      , mContainer(aContainer)
145
0
    {}
146
147
    /**
148
     * The parent frame to use if the inserted children needs to create
149
     * frame(s).  May be null, which signals that  we shouldn't try to
150
     * create frames for the inserted children; either because there are
151
     * no parent frame or because there are multiple insertion points and
152
     * we will call IssueSingleInsertNofications for each child instead.
153
     * mContainer should not be used when mParentFrame is null.
154
     */
155
    nsContainerFrame* mParentFrame;
156
    /**
157
     * The flattened tree parent for the inserted children.
158
     * It's undefined if mParentFrame is null.
159
     */
160
    nsIContent* mContainer;
161
162
    /**
163
     * Whether it is required to insert children one-by-one instead of as a
164
     * range.
165
     */
166
    bool IsMultiple() const;
167
  };
168
169
  /**
170
   * Checks if the children in the range [aStartChild, aEndChild) can be
171
   * inserted/appended to one insertion point together.
172
   *
173
   * If so, returns that insertion point. If not, returns with
174
   * InsertionPoint.mFrame == nullptr and issues single ContentInserted calls
175
   * for each child.
176
   *
177
   * aEndChild = nullptr indicates that we are dealing with an append.
178
   */
179
  InsertionPoint GetRangeInsertionPoint(nsIContent* aStartChild,
180
                                        nsIContent* aEndChild,
181
                                        InsertionKind);
182
183
  // Returns true if parent was recreated due to frameset child, false otherwise.
184
  bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
185
                                nsIContent* aStartChild,
186
                                nsIContent* aEndChild);
187
188
  /**
189
   * For each child in the aStartChild/aEndChild range, calls
190
   * NoteDirtyDescendantsForServo on their flattened tree parents.  This is
191
   * used when content is inserted into the document and we decide that
192
   * we can do lazy frame construction.  It handles children being rebound to
193
   * different insertion points by calling NoteDirtyDescendantsForServo on each
194
   * child's flattened tree parent.  Only used when we are styled by Servo.
195
   */
196
  void LazilyStyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
197
198
  /**
199
   * For each child in the aStartChild/aEndChild range, calls StyleNewChildren
200
   * on their flattened tree parents.  This is used when content is inserted
201
   * into the document and we decide that we cannot do lazy frame construction.
202
   * It handles children being rebound to different insertion points by calling
203
   * StyleNewChildren on each child's flattened tree parent.  Only used when we
204
   * are styled by Servo.
205
   */
206
  void StyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
207
208
public:
209
  /**
210
   * Lazy frame construction is controlled by the InsertionKind parameter of
211
   * nsCSSFrameConstructor::ContentAppended/Inserted. It is true for all
212
   * inserts/appends as passed from the presshell, except for the insert of the
213
   * root element, which is always non-lazy.
214
   *
215
   * Even if the aInsertionKind passed to ContentAppended/Inserted is
216
   * Async we still may not be able to construct lazily, so we call
217
   * MaybeConstructLazily.  MaybeConstructLazily does not allow lazy
218
   * construction if any of the following are true:
219
   *  -we are in chrome
220
   *  -the container is in a native anonymous subtree
221
   *  -the container is XUL
222
   *  -is any of the appended/inserted nodes are XUL or editable
223
   *  -(for inserts) the child is anonymous.  In the append case this function
224
   *   must not be called with anonymous children.
225
   * The XUL and chrome checks are because XBL bindings only get applied at
226
   * frame construction time and some things depend on the bindings getting
227
   * attached synchronously.
228
   *
229
   * If MaybeConstructLazily returns false we construct as usual, but if it
230
   * returns true then it adds NODE_NEEDS_FRAME bits to the newly
231
   * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
232
   * container and up along the parent chain until it hits the root or another
233
   * node with that bit set. Then it posts a restyle event to ensure that a
234
   * flush happens to construct those frames.
235
   *
236
   * When the flush happens the presshell calls
237
   * nsCSSFrameConstructor::CreateNeededFrames. CreateNeededFrames follows any
238
   * nodes with NODE_DESCENDANTS_NEED_FRAMES set down the content tree looking
239
   * for nodes with NODE_NEEDS_FRAME set. It calls ContentAppended for any runs
240
   * of nodes with NODE_NEEDS_FRAME set that are at the end of their childlist,
241
   * and ContentRangeInserted for any other runs that aren't.
242
   *
243
   * If a node is removed from the document then we don't bother unsetting any
244
   * of the lazy bits that might be set on it, its descendants, or any of its
245
   * ancestor nodes because that is a slow operation, the work might be wasted
246
   * if another node gets inserted in its place, and we can clear the bits
247
   * quicker by processing the content tree from top down the next time we call
248
   * CreateNeededFrames. (We do clear the bits when BindToTree is called on any
249
   * nsIContent; so any nodes added to the document will not have any lazy bits
250
   * set.)
251
   */
252
253
  // If aInsertionKind is Async then frame construction of the new children can
254
  // be done lazily.
255
  void ContentAppended(nsIContent* aFirstNewContent, InsertionKind);
256
257
  // If aInsertionkind is Async then frame construction of the new child
258
  // can be done lazily.
259
  void ContentInserted(nsIContent* aChild,
260
                       nsILayoutHistoryState* aFrameState,
261
                       InsertionKind aInsertionKind);
262
263
  // Like ContentInserted but handles inserting the children in the range
264
  // [aStartChild, aEndChild).  aStartChild must be non-null.  aEndChild may be
265
  // null to indicate the range includes all kids after aStartChild.
266
  //
267
  // If aInsertionKind is Async then frame construction of the new children can
268
  // be done lazily. It is only allowed to be Async when inserting a single
269
  // node.
270
  void ContentRangeInserted(nsIContent* aStartChild,
271
                            nsIContent* aEndChild,
272
                            nsILayoutHistoryState* aFrameState,
273
                            InsertionKind aInsertionKind);
274
275
  enum RemoveFlags {
276
    REMOVE_CONTENT,
277
    REMOVE_FOR_RECONSTRUCTION,
278
  };
279
280
  /**
281
   * Recreate or destroy frames for aChild.
282
   *
283
   * aFlags == REMOVE_CONTENT means aChild has been removed from the document.
284
   * aFlags == REMOVE_FOR_RECONSTRUCTION means the caller will reconstruct the
285
   * frames later.
286
   *
287
   * In both the above cases, this method will in some cases try to reconstruct
288
   * frames on some ancestor of aChild.  This can happen regardless of the value
289
   * of aFlags.
290
   *
291
   * The return value indicates whether this "reconstruct an ancestor" action
292
   * took place.  If true is returned, that means that the frame subtree rooted
293
   * at some ancestor of aChild's frame was destroyed and will be reconstructed
294
   * async.
295
   */
296
  bool ContentRemoved(nsIContent* aChild,
297
                      nsIContent* aOldNextSibling,
298
                      RemoveFlags aFlags);
299
300
  void CharacterDataChanged(nsIContent* aContent,
301
                            const CharacterDataChangeInfo& aInfo);
302
303
  // If aContent is a text node that has been optimized away due to being
304
  // whitespace next to a block boundary (or for some other reason), ensure that
305
  // a frame for it is created the next time frames are flushed, if it can
306
  // possibly have a frame at all.
307
  //
308
  // Returns whether there are chances for the frame to be unsuppressed.
309
  bool EnsureFrameForTextNodeIsCreatedAfterFlush(mozilla::dom::CharacterData* aContent);
310
311
  // Generate the child frames and process bindings
312
  void GenerateChildFrames(nsContainerFrame* aFrame);
313
314
  // Should be called when a frame is going to be destroyed and
315
  // WillDestroyFrameTree hasn't been called yet.
316
  void NotifyDestroyingFrame(nsIFrame* aFrame);
317
318
  void RecalcQuotesAndCounters();
319
320
  // Called when any counter style is changed.
321
  void NotifyCounterStylesAreDirty();
322
323
  // Gets called when the presshell is destroying itself and also
324
  // when we tear down our frame tree to reconstruct it
325
  void WillDestroyFrameTree();
326
327
  /**
328
   * Destroy the frames for aContent.  Note that this may destroy frames
329
   * for an ancestor instead.
330
   *
331
   * Returns whether a reconstruct was posted for any ancestor.
332
   */
333
  bool DestroyFramesFor(Element* aElement);
334
335
  // Request to create a continuing frame.  This method never returns null.
336
  nsIFrame* CreateContinuingFrame(nsPresContext*    aPresContext,
337
                                  nsIFrame*         aFrame,
338
                                  nsContainerFrame* aParentFrame,
339
                                  bool              aIsFluid = true);
340
341
  // Copy over fixed frames from aParentFrame's prev-in-flow
342
  nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
343
344
  /**
345
   * Get the insertion point for aChild.
346
   */
347
  InsertionPoint GetInsertionPoint(nsIContent* aChild);
348
349
  /**
350
   * Return the insertion frame of the primary frame of aContent, or its nearest
351
   * ancestor that isn't display:contents.
352
   */
353
  nsContainerFrame* GetContentInsertionFrameFor(nsIContent* aContent);
354
355
  // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame();
356
  // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; }
357
  // This returns the outermost frame for the root element
358
0
  nsContainerFrame* GetRootElementFrame() { return mRootElementFrame; }
359
  // This returns the frame for the root element that does not
360
  // have a psuedo-element style
361
0
  nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
362
0
  nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
363
364
  // Get the frame that is the parent of the root element.
365
  nsContainerFrame* GetDocElementContainingBlock()
366
0
    { return mDocElementContainingBlock; }
367
368
  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
369
370
private:
371
  struct FrameConstructionItem;
372
  class FrameConstructionItemList;
373
374
  nsContainerFrame* ConstructPageFrame(nsIPresShell*      aPresShell,
375
                                       nsContainerFrame*  aParentFrame,
376
                                       nsIFrame*          aPrevPageFrame,
377
                                       nsContainerFrame*& aCanvasFrame);
378
379
  void InitAndRestoreFrame (const nsFrameConstructorState& aState,
380
                            nsIContent*                    aContent,
381
                            nsContainerFrame*              aParentFrame,
382
                            nsIFrame*                      aNewFrame,
383
                            bool                           aAllowCounters = true);
384
385
  already_AddRefed<ComputedStyle> ResolveComputedStyle(nsIContent* aContent);
386
387
  // Add the frame construction items for the given aContent and aParentFrame
388
  // to the list.  This might add more than one item in some rare cases.
389
  // If aSuppressWhiteSpaceOptimizations is true, optimizations that
390
  // may suppress the construction of white-space-only text frames
391
  // must be skipped for these items and items around them.
392
  void AddFrameConstructionItems(nsFrameConstructorState& aState,
393
                                 nsIContent*              aContent,
394
                                 bool                     aSuppressWhiteSpaceOptimizations,
395
                                 const InsertionPoint&    aInsertion,
396
                                 FrameConstructionItemList& aItems);
397
398
  // Helper method for AddFrameConstructionItems etc.
399
  // Unsets the need-frame/restyle bits on aContent.
400
  // return true iff we should attempt to create frames for aContent.
401
  bool ShouldCreateItemsForChild(nsFrameConstructorState& aState,
402
                                 nsIContent* aContent,
403
                                 nsContainerFrame* aParentFrame);
404
405
  // Helper method for AddFrameConstructionItems etc.
406
  // Make sure ShouldCreateItemsForChild() returned true before calling this.
407
  void DoAddFrameConstructionItems(nsFrameConstructorState& aState,
408
                                   nsIContent* aContent,
409
                                   ComputedStyle* aComputedStyle,
410
                                   bool aSuppressWhiteSpaceOptimizations,
411
                                   nsContainerFrame* aParentFrame,
412
                                   FrameConstructionItemList& aItems);
413
414
  // Construct the frames for the document element.  This can return null if the
415
  // document element is display:none, or if the document element has a
416
  // not-yet-loaded XBL binding, or if it's an SVG element that's not <svg>.
417
  nsIFrame* ConstructDocElementFrame(Element*                 aDocElement,
418
                                     nsILayoutHistoryState*   aFrameState);
419
420
  // Set up our mDocElementContainingBlock correctly for the given root
421
  // content.
422
  void SetUpDocElementContainingBlock(nsIContent* aDocElement);
423
424
  /**
425
   * CreateAttributeContent creates a single content/frame combination for an
426
   * |attr(foo)| generated content.
427
   *
428
   * @param aParentContent the parent content for the generated content (that
429
   * is, the originating element).
430
   * @param aParentFrame the parent frame for the generated frame
431
   * @param aAttrNamespace the namespace of the attribute in question
432
   * @param aAttrName the localname of the attribute
433
   * @param aComputedStyle the style to use
434
   * @param aGeneratedContent the array of generated content to append the
435
   *                          created content to.
436
   * @param [out] aNewContent the content node we create
437
   * @param [out] aNewFrame the new frame we create
438
   */
439
  void CreateAttributeContent(const Element& aParentContent,
440
                              nsIFrame* aParentFrame,
441
                              int32_t aAttrNamespace,
442
                              nsAtom* aAttrName,
443
                              ComputedStyle* aComputedStyle,
444
                              nsCOMArray<nsIContent>& aGeneratedContent,
445
                              nsIContent** aNewContent,
446
                              nsIFrame** aNewFrame);
447
448
  /**
449
   * Create a text node containing the given string. If aText is non-null
450
   * then we also set aText to the returned node.
451
   */
452
  already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState,
453
                                                    const nsString& aString,
454
                                                    RefPtr<nsTextNode>* aText,
455
                                                    nsGenConInitializer* aInitializer);
456
457
  /**
458
   * Create a content node for the given generated content style.
459
   * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
460
   * to the document, and creating frames for it.
461
   * @param aOriginatingElement is the node that has the before/after style.
462
   * @param aComputedStyle is the 'before' or 'after' pseudo-element style.
463
   * @param aContentIndex is the index of the content item to create
464
   */
465
  already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
466
                                                      const Element& aOriginatingElement,
467
                                                      ComputedStyle& aComputedStyle,
468
                                                      uint32_t aContentIndex);
469
470
  // aParentFrame may be null; this method doesn't use it directly in any case.
471
  void CreateGeneratedContentItem(nsFrameConstructorState& aState,
472
                                  nsContainerFrame* aParentFrame,
473
                                  Element& aOriginatingElement,
474
                                  ComputedStyle&,
475
                                  CSSPseudoElementType aPseudoElement,
476
                                  FrameConstructionItemList& aItems);
477
478
  // This method can change aFrameList: it can chop off the beginning and put
479
  // it in aParentFrame while putting the remainder into a ib-split sibling of
480
  // aParentFrame.  aPrevSibling must be the frame after which aFrameList is to
481
  // be placed on aParentFrame's principal child list.  It may be null if
482
  // aFrameList is being added at the beginning of the child list.
483
  void AppendFramesToParent(nsFrameConstructorState&       aState,
484
                            nsContainerFrame*              aParentFrame,
485
                            nsFrameItems&                  aFrameList,
486
                            nsIFrame*                      aPrevSibling,
487
                            bool                           aIsRecursiveCall = false);
488
489
  // BEGIN TABLE SECTION
490
  /**
491
   * Construct a table wrapper frame. This is the FrameConstructionData
492
   * callback used for the job.
493
   */
494
  nsIFrame* ConstructTable(nsFrameConstructorState& aState,
495
                           FrameConstructionItem&   aItem,
496
                           nsContainerFrame*        aParentFrame,
497
                           const nsStyleDisplay*    aDisplay,
498
                           nsFrameItems&            aFrameItems);
499
500
  /**
501
   * FrameConstructionData callback for constructing table rows and row groups.
502
   */
503
  nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
504
                                        FrameConstructionItem&   aItem,
505
                                        nsContainerFrame*        aParentFrame,
506
                                        const nsStyleDisplay*    aStyleDisplay,
507
                                        nsFrameItems&            aFrameItems);
508
509
  /**
510
   * FrameConstructionData callback used for constructing table columns.
511
   */
512
  nsIFrame* ConstructTableCol(nsFrameConstructorState& aState,
513
                              FrameConstructionItem&   aItem,
514
                              nsContainerFrame*        aParentFrame,
515
                              const nsStyleDisplay*    aStyleDisplay,
516
                              nsFrameItems&            aFrameItems);
517
518
  /**
519
   * FrameConstructionData callback used for constructing table cells.
520
   */
521
  nsIFrame* ConstructTableCell(nsFrameConstructorState& aState,
522
                               FrameConstructionItem&   aItem,
523
                               nsContainerFrame*        aParentFrame,
524
                               const nsStyleDisplay*    aStyleDisplay,
525
                               nsFrameItems&            aFrameItems);
526
527
private:
528
  /* An enum of possible parent types for anonymous table or ruby object
529
     construction */
530
  enum ParentType {
531
    eTypeBlock = 0, /* This includes all non-table-related frames */
532
    eTypeRow,
533
    eTypeRowGroup,
534
    eTypeColGroup,
535
    eTypeTable,
536
    eTypeRuby,
537
    eTypeRubyBase,
538
    eTypeRubyBaseContainer,
539
    eTypeRubyText,
540
    eTypeRubyTextContainer,
541
    eParentTypeCount
542
  };
543
544
  /* 4 bits is enough to handle our ParentType values */
545
0
#define FCDATA_PARENT_TYPE_OFFSET 28
546
  /* Macro to get the desired parent type out of an mBits member of
547
     FrameConstructionData */
548
#define FCDATA_DESIRED_PARENT_TYPE(_bits)           \
549
0
  ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
550
  /* Macro to create FrameConstructionData bits out of a desired parent type */
551
#define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type)     \
552
0
  (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
553
554
  /* Get the parent type that aParentFrame has. */
555
0
  static ParentType GetParentType(nsIFrame* aParentFrame) {
556
0
    return GetParentType(aParentFrame->Type());
557
0
  }
558
559
  /* Get the parent type for the given LayoutFrameType */
560
  static ParentType GetParentType(mozilla::LayoutFrameType aFrameType);
561
562
0
  static bool IsRubyParentType(ParentType aParentType) {
563
0
    return (aParentType == eTypeRuby ||
564
0
            aParentType == eTypeRubyBase ||
565
0
            aParentType == eTypeRubyBaseContainer ||
566
0
            aParentType == eTypeRubyText ||
567
0
            aParentType == eTypeRubyTextContainer);
568
0
  }
569
570
0
  static bool IsTableParentType(ParentType aParentType) {
571
0
    return (aParentType == eTypeTable ||
572
0
            aParentType == eTypeRow ||
573
0
            aParentType == eTypeRowGroup ||
574
0
            aParentType == eTypeColGroup);
575
0
  }
576
577
  /* A constructor function that just creates an nsIFrame object.  The caller
578
     is responsible for initializing the object, adding it to frame lists,
579
     constructing frames for the children, etc.
580
581
     @param nsIPresShell the presshell whose arena should be used to allocate
582
                         the frame.
583
     @param ComputedStyle the style to use for the frame. */
584
  typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, ComputedStyle*);
585
  typedef nsContainerFrame* (* ContainerFrameCreationFunc)(nsIPresShell*, ComputedStyle*);
586
  typedef nsBlockFrame* (* BlockFrameCreationFunc)(nsIPresShell*, ComputedStyle*);
587
588
  /* A function that can be used to get a FrameConstructionData.  Such
589
     a function is allowed to return null.
590
591
     @param nsIContent the node for which the frame is being constructed.
592
     @param ComputedStyle the style to be used for the frame.
593
  */
594
  struct FrameConstructionData;
595
  typedef const FrameConstructionData*
596
    (* FrameConstructionDataGetter)(const Element&, ComputedStyle&);
597
598
  /* A constructor function that's used for complicated construction tasks.
599
     This is expected to create the new frame, initialize it, add whatever
600
     needs to be added to aFrameItems (XXXbz is that really necessary?  Could
601
     caller add?  Might there be cases when the returned frame or its
602
     placeholder is not the thing that ends up in aFrameItems?  If not, would
603
     it be safe to do the add into the frame construction state after
604
     processing kids?  Look into this as a followup!), process children as
605
     needed, etc.  It is NOT expected to deal with setting the frame on the
606
     content.
607
608
     @param aState the frame construction state to use.
609
     @param aItem the frame construction item to use
610
     @param aParentFrame the frame to set as the parent of the
611
                         newly-constructed frame.
612
     @param aStyleDisplay the display struct from aItem's mComputedStyle
613
     @param aFrameItems the frame list to add the new frame (or its
614
                        placeholder) to.
615
     @return the frame that was constructed.  This frame is what the caller
616
             will set as the frame on the content.  Guaranteed non-null.
617
  */
618
  typedef nsIFrame*
619
    (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
620
                                                    FrameConstructionItem& aItem,
621
                                                    nsContainerFrame* aParentFrame,
622
                                                    const nsStyleDisplay* aStyleDisplay,
623
                                                    nsFrameItems& aFrameItems);
624
625
  /* Bits that modify the way a FrameConstructionData is handled */
626
627
  /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
628
     be set as the primary frame on the content node.  This should only be used
629
     in very rare cases when we create more than one frame for a given content
630
     node. */
631
0
#define FCDATA_SKIP_FRAMESET 0x1
632
  /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
633
     FrameConstructionData is a getter function that can be used to get the
634
     actual FrameConstructionData to use. */
635
0
#define FCDATA_FUNC_IS_DATA_GETTER 0x2
636
  /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
637
     has an mFullConstructor.  In this case, there is no relevant mData or
638
     mFunc */
639
0
#define FCDATA_FUNC_IS_FULL_CTOR 0x4
640
  /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
641
     float or be absolutely positioned.  This can also be used with
642
     FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
643
     function will do. */
644
0
#define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
645
  /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
646
     null absolute containing block before processing children for this
647
     frame.  If this is not set, the frame will be pushed as the
648
     absolute containing block as needed, based on its style */
649
0
#define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
650
  /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
651
     will be wrapped in blocks.  This is only usable for MathML at the
652
     moment. */
653
0
#define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
654
  /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
655
     content.  If this bit is set, nothing else in the struct needs to be
656
     set. */
657
0
#define FCDATA_SUPPRESS_FRAME 0x40
658
  /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
659
     a scrollframe if its overflow type so requires. */
660
0
#define FCDATA_MAY_NEED_SCROLLFRAME 0x80
661
#ifdef MOZ_XUL
662
  /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame.  These need
663
     some really weird special handling.  */
664
0
#define FCDATA_IS_POPUP 0x100
665
#endif /* MOZ_XUL */
666
  /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
667
     absolute containing block, no matter what its style says. */
668
0
#define FCDATA_SKIP_ABSPOS_PUSH 0x200
669
  /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
670
     content when processing kids of this frame.  This should not be used with
671
     FCDATA_FUNC_IS_FULL_CTOR */
672
0
#define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
673
  /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
674
     table-related thing and we should not attempt to fetch a table-cell parent
675
     for it if it's inside another table-related frame. */
676
0
#define FCDATA_IS_TABLE_PART 0x800
677
  /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
678
     inline box. */
679
0
#define FCDATA_IS_INLINE 0x1000
680
  /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
681
     return true for IsFrameOfType(nsIFrame::eLineParticipant) */
682
0
#define FCDATA_IS_LINE_PARTICIPANT 0x2000
683
  /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
684
     induce a line break boundary before and after itself. */
685
0
#define FCDATA_IS_LINE_BREAK 0x4000
686
  /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
687
     children of a block (i.e. allow ::first-letter/line).
688
     This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
689
0
#define FCDATA_ALLOW_BLOCK_STYLES 0x8000
690
  /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
691
     FrameConstructionItem instead of trying to process the content's children.
692
     This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
693
     The child items might still need table pseudo processing. */
694
0
#define FCDATA_USE_CHILD_ITEMS 0x10000
695
  /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
696
     would have been scrollable but has been forced to be
697
     non-scrollable due to being in a paginated context. */
698
0
#define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
699
  /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
700
     block formatting context wrapper around the kids of this frame
701
     using the FrameConstructionData's mPseudoAtom for its anonymous
702
     box type. */
703
0
#define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
704
  /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
705
     an SVG text frame. */
706
0
#define FCDATA_IS_SVG_TEXT 0x80000
707
  /**
708
   * When FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, this bit says
709
   * if we should create a grid/flex/columnset container instead of
710
   * a block wrapper when the styles says so.
711
   */
712
0
#define FCDATA_ALLOW_GRID_FLEX_COLUMNSET 0x200000
713
  /**
714
   * Whether the kids of this FrameConstructionData should be flagged as having
715
   * a wrapper anon box parent.  This should only be set if
716
   * FCDATA_USE_CHILD_ITEMS is set.
717
   */
718
0
#define FCDATA_IS_WRAPPER_ANON_BOX 0x400000
719
720
  /* Structure representing information about how a frame should be
721
     constructed.  */
722
  struct FrameConstructionData {
723
    // Flag bits that can modify the way the construction happens
724
    uint32_t mBits;
725
    // We have exactly one of three types of functions, so use a union for
726
    // better cache locality for the ones that aren't pointer-to-member.  That
727
    // one needs to be separate, because we can't cast between it and the
728
    // others and hence wouldn't be able to initialize the union without a
729
    // constructor and all the resulting generated code.  See documentation
730
    // above for FrameCreationFunc, FrameConstructionDataGetter, and
731
    // FrameFullConstructor to see what the functions would do.
732
    union Func {
733
      FrameCreationFunc mCreationFunc;
734
      FrameConstructionDataGetter mDataGetter;
735
    } mFunc;
736
    FrameFullConstructor mFullConstructor;
737
    // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
738
    // anonymous box type to use for that wrapper.
739
    nsICSSAnonBoxPseudo * const * const mAnonBoxPseudo;
740
  };
741
742
  /* Structure representing a mapping of an atom to a FrameConstructionData.
743
     This can be used with non-static atoms, assuming that the nsAtom* is
744
     stored somewhere that this struct can point to (that is, a static
745
     nsAtom*) and that it's allocated before the struct is ever used. */
746
  struct FrameConstructionDataByTag {
747
    // Pointer to nsStaticAtom* is used because we want to initialize this
748
    // statically, so before our atom tables are set up.
749
    const nsStaticAtom * const * const mTag;
750
    const FrameConstructionData mData;
751
  };
752
753
  /* Structure representing a mapping of an integer to a
754
     FrameConstructionData. There are no magic integer values here. */
755
  struct FrameConstructionDataByInt {
756
    /* Could be used for display or whatever else */
757
    const int32_t mInt;
758
    const FrameConstructionData mData;
759
  };
760
761
  struct FrameConstructionDataByDisplay {
762
#ifdef DEBUG
763
    const mozilla::StyleDisplay mDisplay;
764
#endif
765
    const FrameConstructionData mData;
766
  };
767
768
#ifdef DEBUG
769
#define FCDATA_FOR_DISPLAY(_display, _fcdata) \
770
  { _display, _fcdata }
771
#else
772
#define FCDATA_FOR_DISPLAY(_display, _fcdata) \
773
0
  { _fcdata }
774
#endif
775
776
  /* Structure that has a FrameConstructionData and style pseudo-type
777
     for a table pseudo-frame */
778
  struct PseudoParentData {
779
    const FrameConstructionData mFCData;
780
    nsICSSAnonBoxPseudo * const * const mPseudoType;
781
  };
782
  /* Array of such structures that we use to properly construct table
783
     pseudo-frames as needed */
784
  static const PseudoParentData sPseudoParentData[eParentTypeCount];
785
786
  // The information that concerns the frame constructor after loading an XBL
787
  // binding.
788
  //
789
  // This is expected to just be used temporarily to aggregate the different
790
  // objects that LoadXBLBindingIfNeeded returns.
791
  struct MOZ_STACK_CLASS XBLBindingLoadInfo
792
  {
793
    RefPtr<ComputedStyle> mStyle;
794
    mozilla::UniquePtr<PendingBinding> mPendingBinding;
795
    nsAtom* mTag = nullptr;
796
797
    // For the 'no binding loaded' case.
798
    XBLBindingLoadInfo(nsIContent&, ComputedStyle&);
799
800
    // For the case we actually load an XBL binding.
801
    XBLBindingLoadInfo(already_AddRefed<ComputedStyle>&& aStyle,
802
                       mozilla::UniquePtr<PendingBinding> aPendingBinding,
803
                       nsAtom* aTag);
804
805
    // For the error case.
806
    XBLBindingLoadInfo();
807
  };
808
809
  // Returns null mStyle / mTag members to signal an error.
810
  XBLBindingLoadInfo LoadXBLBindingIfNeeded(nsIContent&,
811
                                            ComputedStyle&,
812
                                            uint32_t aFlags);
813
814
  const FrameConstructionData* FindDataForContent(nsIContent&,
815
                                                  ComputedStyle&,
816
                                                  nsIFrame* aParentFrame,
817
                                                  nsAtom* aTag,
818
                                                  uint32_t aFlags);
819
820
  // aParentFrame might be null.  If it is, that means it was an inline frame.
821
  static const FrameConstructionData* FindTextData(const Text&,
822
                                                   nsIFrame* aParentFrame);
823
  const FrameConstructionData* FindElementData(const Element&,
824
                                               ComputedStyle&,
825
                                               nsIFrame* aParentFrame,
826
                                               nsAtom* aTag,
827
                                               uint32_t aFlags);
828
  const FrameConstructionData* FindElementTagData(const Element&,
829
                                                  ComputedStyle&,
830
                                                  nsIFrame* aParentFrame,
831
                                                  nsAtom* aTag,
832
                                                  uint32_t aFlags);
833
834
  /* A function that takes an integer, content, style, and array of
835
     FrameConstructionDataByInts and finds the appropriate frame construction
836
     data to use and returns it.  This can return null if none of the integers
837
     match or if the matching integer has a FrameConstructionDataGetter that
838
     returns null. */
839
  static const FrameConstructionData*
840
    FindDataByInt(int32_t aInt,
841
                  const Element&,
842
                  ComputedStyle&,
843
                  const FrameConstructionDataByInt* aDataPtr,
844
                  uint32_t aDataLength);
845
846
  /**
847
   * A function that takes a tag, content, style, and array of
848
   * FrameConstructionDataByTags and finds the appropriate frame construction
849
   * data to use and returns it.
850
   *
851
   * This can return null if none of the tags match or if the matching tag has a
852
   * FrameConstructionDataGetter that returns null. In the case that the tags
853
   * actually match, aTagFound will be true, even if the return value is null.
854
   */
855
  static const FrameConstructionData*
856
    FindDataByTag(nsAtom* aTag,
857
                  const Element& aElement,
858
                  ComputedStyle& aComputedStyle,
859
                  const FrameConstructionDataByTag* aDataPtr,
860
                  uint32_t aDataLength);
861
862
  /* A class representing a list of FrameConstructionItems.  Instances of this
863
     class are only created as AutoFrameConstructionItemList, or as a member
864
     of FrameConstructionItem. */
865
  class FrameConstructionItemList
866
  {
867
  public:
868
    void Reset(nsCSSFrameConstructor* aFCtor)
869
0
    {
870
0
      Destroy(aFCtor);
871
0
      this->~FrameConstructionItemList();
872
0
      new (this) FrameConstructionItemList();
873
0
    }
874
875
0
    void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; }
876
0
    void SetLineBoundaryAtEnd(bool aBoundary) { mLineBoundaryAtEnd = aBoundary; }
877
0
    void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) {
878
0
      mParentHasNoXBLChildren = aHasNoXBLChildren;
879
0
    }
880
0
    bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
881
0
    bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
882
0
    bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
883
0
    bool IsEmpty() const { return mItems.isEmpty(); }
884
0
    bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; }
885
0
    bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
886
0
    bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
887
0
    bool AllWantParentType(ParentType aDesiredParentType) const {
888
0
      return mDesiredParentCounts[aDesiredParentType] == mItemCount;
889
0
    }
890
891
    // aSuppressWhiteSpaceOptimizations is true if optimizations that
892
    // skip constructing whitespace frames for this item or items
893
    // around it cannot be performed.
894
    // Also, the return value is always non-null, thanks to infallible 'new'.
895
    FrameConstructionItem* AppendItem(nsCSSFrameConstructor* aFCtor,
896
                                      const FrameConstructionData* aFCData,
897
                                      nsIContent* aContent,
898
                                      PendingBinding* aPendingBinding,
899
                                      already_AddRefed<ComputedStyle>&& aComputedStyle,
900
                                      bool aSuppressWhiteSpaceOptimizations)
901
0
    {
902
0
      FrameConstructionItem* item =
903
0
        new (aFCtor) FrameConstructionItem(aFCData, aContent,
904
0
                                           aPendingBinding, std::move(aComputedStyle),
905
0
                                           aSuppressWhiteSpaceOptimizations);
906
0
      mItems.insertBack(item);
907
0
      ++mItemCount;
908
0
      ++mDesiredParentCounts[item->DesiredParentType()];
909
0
      return item;
910
0
    }
911
912
    // Arguments are the same as AppendItem().
913
    FrameConstructionItem* PrependItem(nsCSSFrameConstructor* aFCtor,
914
                                       const FrameConstructionData* aFCData,
915
                                       nsIContent* aContent,
916
                                       PendingBinding* aPendingBinding,
917
                                       already_AddRefed<ComputedStyle>&& aComputedStyle,
918
                                       bool aSuppressWhiteSpaceOptimizations)
919
0
    {
920
0
      FrameConstructionItem* item =
921
0
        new (aFCtor) FrameConstructionItem(aFCData, aContent,
922
0
                                           aPendingBinding, std::move(aComputedStyle),
923
0
                                           aSuppressWhiteSpaceOptimizations);
924
0
      mItems.insertFront(item);
925
0
      ++mItemCount;
926
0
      ++mDesiredParentCounts[item->DesiredParentType()];
927
0
      return item;
928
0
    }
929
930
0
    void InlineItemAdded() { ++mInlineCount; }
931
0
    void BlockItemAdded() { ++mBlockCount; }
932
0
    void LineParticipantItemAdded() { ++mLineParticipantCount; }
933
934
    class Iterator {
935
    public:
936
      explicit Iterator(FrameConstructionItemList& aList)
937
        : mCurrent(aList.mItems.getFirst())
938
        , mList(aList)
939
0
      {}
940
      Iterator(const Iterator& aOther) :
941
        mCurrent(aOther.mCurrent),
942
        mList(aOther.mList)
943
0
      {}
944
945
0
      bool operator==(const Iterator& aOther) const {
946
0
        MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
947
0
        return mCurrent == aOther.mCurrent;
948
0
      }
949
0
      bool operator!=(const Iterator& aOther) const {
950
0
        return !(*this == aOther);
951
0
      }
952
0
      Iterator& operator=(const Iterator& aOther) {
953
0
        MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
954
0
        mCurrent = aOther.mCurrent;
955
0
        return *this;
956
0
      }
957
958
0
      FrameConstructionItemList* List() {
959
0
        return &mList;
960
0
      }
961
962
0
      FrameConstructionItem& item() {
963
0
        MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
964
0
        return *mCurrent;
965
0
      }
966
967
0
      const FrameConstructionItem& item() const {
968
0
        MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
969
0
        return *mCurrent;
970
0
      }
971
972
0
      bool IsDone() const { return mCurrent == nullptr; }
973
0
      bool AtStart() const { return mCurrent == mList.mItems.getFirst(); }
974
0
      void Next() {
975
0
        NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
976
0
        mCurrent = mCurrent->getNext();
977
0
      }
978
0
      void Prev() {
979
0
        NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
980
0
        mCurrent = mCurrent ? mCurrent->getPrevious() : mList.mItems.getLast();
981
0
      }
982
0
      void SetToEnd() { mCurrent = nullptr; }
983
984
      // Skip over all items that want the given parent type. Return whether
985
      // the iterator is done after doing that.  The iterator must not be done
986
      // when this is called.
987
      inline bool SkipItemsWantingParentType(ParentType aParentType);
988
989
      // Skip over all items that want a parent type different from the given
990
      // one.  Return whether the iterator is done after doing that.  The
991
      // iterator must not be done when this is called.
992
      inline bool SkipItemsNotWantingParentType(ParentType aParentType);
993
994
      // Skip over non-replaced inline frames and positioned frames.
995
      // Return whether the iterator is done after doing that.
996
      // The iterator must not be done when this is called.
997
      inline bool SkipItemsThatNeedAnonFlexOrGridItem(
998
        const nsFrameConstructorState& aState,
999
        bool aIsWebkitBox);
1000
1001
      // Skip to the first frame that is a non-replaced inline or is
1002
      // positioned.  Return whether the iterator is done after doing that.
1003
      // The iterator must not be done when this is called.
1004
      inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
1005
        const nsFrameConstructorState& aState,
1006
        bool aIsWebkitBox);
1007
1008
      // Skip over all items that do not want a ruby parent.  Return whether
1009
      // the iterator is done after doing that.  The iterator must not be done
1010
      // when this is called.
1011
      inline bool SkipItemsNotWantingRubyParent();
1012
1013
      // Skip over whitespace.  Return whether the iterator is done after doing
1014
      // that.  The iterator must not be done, and must be pointing to a
1015
      // whitespace item when this is called.
1016
      inline bool SkipWhitespace(nsFrameConstructorState& aState);
1017
1018
      // Remove the item pointed to by this iterator from its current list and
1019
      // Append it to aTargetList.  This iterator is advanced to point to the
1020
      // next item in its list.  aIter must not be done.  aTargetList must not be
1021
      // the list this iterator is iterating over..
1022
      void AppendItemToList(FrameConstructionItemList& aTargetList);
1023
1024
      // As above, but moves all items starting with this iterator until we
1025
      // get to aEnd; the item pointed to by aEnd is not stolen.  This method
1026
      // might have optimizations over just looping and doing StealItem for
1027
      // some special cases.  After this method returns, this iterator will
1028
      // point to the item aEnd points to now; aEnd is not modified.
1029
      // aTargetList must not be the list this iterator is iterating over.
1030
      void AppendItemsToList(nsCSSFrameConstructor*     aFCtor,
1031
                             const Iterator&            aEnd,
1032
                             FrameConstructionItemList& aTargetList);
1033
1034
      // Insert aItem in this iterator's list right before the item pointed to
1035
      // by this iterator.  After the insertion, this iterator will continue to
1036
      // point to the item it now points to (the one just after the
1037
      // newly-inserted item).  This iterator is allowed to be done; in that
1038
      // case this call just appends the given item to the list.
1039
      void InsertItem(FrameConstructionItem* aItem);
1040
1041
      // Delete the items between this iterator and aEnd, including the item
1042
      // this iterator currently points to but not including the item pointed
1043
      // to by aEnd.  When this returns, this iterator will point to the same
1044
      // item as aEnd.  This iterator must not equal aEnd when this method is
1045
      // called.
1046
      void DeleteItemsTo(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd);
1047
1048
    private:
1049
      FrameConstructionItem* mCurrent;
1050
      FrameConstructionItemList& mList;
1051
    };
1052
1053
  protected:
1054
    FrameConstructionItemList() :
1055
      mInlineCount(0),
1056
      mBlockCount(0),
1057
      mLineParticipantCount(0),
1058
      mItemCount(0),
1059
      mLineBoundaryAtStart(false),
1060
      mLineBoundaryAtEnd(false),
1061
      mParentHasNoXBLChildren(false)
1062
0
    {
1063
0
      MOZ_COUNT_CTOR(FrameConstructionItemList);
1064
0
      memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
1065
0
    }
1066
1067
    void Destroy(nsCSSFrameConstructor* aFCtor)
1068
0
    {
1069
0
      while (FrameConstructionItem* item = mItems.popFirst()) {
1070
0
        item->Delete(aFCtor);
1071
0
      }
1072
0
    }
1073
1074
    // Prevent stack instances (except as AutoFrameConstructionItemList).
1075
    friend struct FrameConstructionItem;
1076
    ~FrameConstructionItemList()
1077
0
    {
1078
0
      MOZ_COUNT_DTOR(FrameConstructionItemList);
1079
0
      MOZ_ASSERT(mItems.isEmpty(), "leaking");
1080
0
    }
1081
  private:
1082
    // Not allocated from the heap!
1083
    void* operator new(size_t) = delete;
1084
    void* operator new[](size_t) = delete;
1085
#ifdef _MSC_VER  /* Visual Studio */
1086
    void operator delete(void*) { MOZ_CRASH("FrameConstructionItemList::del"); }
1087
#else
1088
    void operator delete(void*) = delete;
1089
#endif
1090
    void operator delete[](void*) = delete;
1091
    // Placement new is used by Reset().
1092
0
    void* operator new(size_t, void* aPtr) { return aPtr; }
1093
1094
    struct UndisplayedItem {
1095
      UndisplayedItem(nsIContent* aContent, ComputedStyle* aComputedStyle) :
1096
        mContent(aContent), mComputedStyle(aComputedStyle)
1097
0
      {}
1098
1099
      nsIContent * const mContent;
1100
      RefPtr<ComputedStyle> mComputedStyle;
1101
    };
1102
1103
    // Adjust our various counts for aItem being added or removed.  aDelta
1104
    // should be either +1 or -1 depending on which is happening.
1105
    void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
1106
1107
    mozilla::LinkedList<FrameConstructionItem> mItems;
1108
    uint32_t mInlineCount;
1109
    uint32_t mBlockCount;
1110
    uint32_t mLineParticipantCount;
1111
    uint32_t mItemCount;
1112
    uint32_t mDesiredParentCounts[eParentTypeCount];
1113
    // True if there is guaranteed to be a line boundary before the
1114
    // frames created by these items
1115
    bool mLineBoundaryAtStart;
1116
    // True if there is guaranteed to be a line boundary after the
1117
    // frames created by these items
1118
    bool mLineBoundaryAtEnd;
1119
    // True if the parent is guaranteed to have no XBL anonymous children
1120
    bool mParentHasNoXBLChildren;
1121
  };
1122
1123
  /* A struct representing a list of FrameConstructionItems on the stack. */
1124
  struct MOZ_RAII AutoFrameConstructionItemList final
1125
    : public FrameConstructionItemList
1126
  {
1127
    template<typename... Args>
1128
    explicit AutoFrameConstructionItemList(nsCSSFrameConstructor* aFCtor, Args&&... args)
1129
      : FrameConstructionItemList(std::forward<Args>(args)...)
1130
      , mFCtor(aFCtor)
1131
0
    { MOZ_ASSERT(mFCtor); }
1132
0
    ~AutoFrameConstructionItemList() { Destroy(mFCtor); }
1133
  private:
1134
    nsCSSFrameConstructor* const mFCtor;
1135
  };
1136
1137
  typedef FrameConstructionItemList::Iterator FCItemIterator;
1138
1139
  /* A struct representing an item for which frames might need to be
1140
   * constructed.  This contains all the information needed to construct the
1141
   * frame other than the parent frame and whatever would be stored in the
1142
   * frame constructor state.  You probably want to use
1143
   * AutoFrameConstructionItem instead of this struct. */
1144
  struct FrameConstructionItem final
1145
    : public mozilla::LinkedListElement<FrameConstructionItem>
1146
  {
1147
    FrameConstructionItem(const FrameConstructionData* aFCData,
1148
                          nsIContent* aContent,
1149
                          PendingBinding* aPendingBinding,
1150
                          already_AddRefed<ComputedStyle>&& aComputedStyle,
1151
                          bool aSuppressWhiteSpaceOptimizations)
1152
    : mFCData(aFCData), mContent(aContent),
1153
      mPendingBinding(aPendingBinding), mComputedStyle(std::move(aComputedStyle)),
1154
      mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
1155
      mIsText(false), mIsGeneratedContent(false),
1156
      mIsAnonymousContentCreatorContent(false),
1157
      mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),
1158
      mIsPopup(false),
1159
      mIsLineParticipant(false)
1160
0
    {
1161
0
      MOZ_COUNT_CTOR(FrameConstructionItem);
1162
0
    }
1163
1164
    void* operator new(size_t, nsCSSFrameConstructor* aFCtor)
1165
0
    { return aFCtor->AllocateFCItem(); }
1166
1167
    void Delete(nsCSSFrameConstructor* aFCtor)
1168
0
    {
1169
0
      mChildItems.Destroy(aFCtor);
1170
0
      if (mIsGeneratedContent) {
1171
0
        mContent->UnbindFromTree();
1172
0
        NS_RELEASE(mContent);
1173
0
      }
1174
0
      this->~FrameConstructionItem();
1175
0
      aFCtor->FreeFCItem(this);
1176
0
    }
1177
1178
0
    ParentType DesiredParentType() {
1179
0
      return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
1180
0
    }
1181
1182
    // Indicates whether (when in a flex or grid container) this item needs
1183
    // to be wrapped in an anonymous block.  (Note that we implement
1184
    // -webkit-box/-webkit-inline-box using our standard flexbox frame class,
1185
    // but we use different rules for what gets wrapped. The aIsWebkitBox
1186
    // parameter here tells us whether to use those different rules.)
1187
    bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
1188
                                 bool aIsWebkitBox);
1189
1190
    // Don't call this unless the frametree really depends on the answer!
1191
    // Especially so for generated content, where we don't want to reframe
1192
    // things.
1193
    bool IsWhitespace(nsFrameConstructorState& aState) const;
1194
1195
0
    bool IsLineBoundary() const {
1196
0
      return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
1197
0
    }
1198
1199
    // Child frame construction items.
1200
    FrameConstructionItemList mChildItems;
1201
1202
    // The FrameConstructionData to use.
1203
    const FrameConstructionData* mFCData;
1204
    // The nsIContent node to use when initializing the new frame.
1205
    nsIContent* mContent;
1206
    // The PendingBinding for this frame construction item, if any.  May be
1207
    // null.  We maintain a list of PendingBindings in the frame construction
1208
    // state in the order in which AddToAttachedQueue should be called on them:
1209
    // depth-first, post-order traversal order.  Since we actually traverse the
1210
    // DOM in a mix of breadth-first and depth-first, it is the responsibility
1211
    // of whoever constructs FrameConstructionItem kids of a given
1212
    // FrameConstructionItem to push its mPendingBinding as the current
1213
    // insertion point before doing so and pop it afterward.
1214
    PendingBinding* mPendingBinding;
1215
    // The style to use for creating the new frame.
1216
    RefPtr<ComputedStyle> mComputedStyle;
1217
    // Whether optimizations to skip constructing textframes around
1218
    // this content need to be suppressed.
1219
    bool mSuppressWhiteSpaceOptimizations:1;
1220
    // Whether this is a text content item.
1221
    bool mIsText:1;
1222
    // Whether this is a generated content container.
1223
    // If it is, mContent is a strong pointer.
1224
    bool mIsGeneratedContent:1;
1225
    // Whether this is an item for nsIAnonymousContentCreator content.
1226
    bool mIsAnonymousContentCreatorContent:1;
1227
    // Whether this is an item for the root popupgroup.
1228
    bool mIsRootPopupgroup:1;
1229
    // Whether construction from this item will create only frames that are
1230
    // IsInlineOutside() in the principal child list.  This is not precise, but
1231
    // conservative: if true the frames will really be inline, whereas if false
1232
    // they might still all be inline.
1233
    bool mIsAllInline:1;
1234
    // Whether construction from this item will create only frames that are
1235
    // IsBlockOutside() in the principal child list.  This is not precise, but
1236
    // conservative: if true the frames will really be blocks, whereas if false
1237
    // they might still be blocks (and in particular, out-of-flows that didn't
1238
    // find a containing block).
1239
    bool mIsBlock:1;
1240
    // Whether construction from this item will create a popup that needs to
1241
    // go into the global popup items.
1242
    bool mIsPopup:1;
1243
    // Whether this item should be treated as a line participant
1244
    bool mIsLineParticipant:1;
1245
1246
  private:
1247
    // Not allocated from the general heap - instead, use the new/Delete APIs
1248
    // that take a nsCSSFrameConstructor* (which manages our arena allocation).
1249
    void* operator new(size_t) = delete;
1250
    void* operator new[](size_t) = delete;
1251
#ifdef _MSC_VER  /* Visual Studio */
1252
    void operator delete(void*) { MOZ_CRASH("FrameConstructionItem::delete"); }
1253
#else
1254
    void operator delete(void*) = delete;
1255
#endif
1256
    void operator delete[](void*) = delete;
1257
    FrameConstructionItem(const FrameConstructionItem& aOther) = delete; /* not implemented */
1258
    // Not allocated from the stack!
1259
    ~FrameConstructionItem()
1260
0
    {
1261
0
      MOZ_COUNT_DTOR(FrameConstructionItem);
1262
0
      MOZ_ASSERT(mChildItems.IsEmpty(), "leaking");
1263
0
    }
1264
  };
1265
1266
  /**
1267
   * Convenience struct to assist in managing a temporary FrameConstructionItem
1268
   * using a local variable. Castable to FrameConstructionItem so that it can
1269
   * be passed transparently to functions that expect that type.
1270
   * (This struct exists because FrameConstructionItem is arena-allocated, and
1271
   * it's nice to abstract away its allocation/deallocation.)
1272
   */
1273
  struct MOZ_RAII AutoFrameConstructionItem final
1274
  {
1275
    template<typename... Args>
1276
    explicit AutoFrameConstructionItem(nsCSSFrameConstructor* aFCtor, Args&&... args)
1277
      : mFCtor(aFCtor)
1278
      , mItem(new (aFCtor) FrameConstructionItem(std::forward<Args>(args)...))
1279
0
    { MOZ_ASSERT(mFCtor); }
1280
0
    ~AutoFrameConstructionItem() { mItem->Delete(mFCtor); }
1281
0
    operator FrameConstructionItem&() { return *mItem; }
1282
  private:
1283
    nsCSSFrameConstructor* const mFCtor;
1284
    FrameConstructionItem* const mItem;
1285
  };
1286
1287
  /**
1288
   * Function to create the anonymous flex or grid items that we need.
1289
   * If aParentFrame is not a nsFlexContainerFrame or nsGridContainerFrame then
1290
   * this method is a NOP.
1291
   * @param aItems the child frame construction items before pseudo creation
1292
   * @param aParentFrame the parent frame
1293
   */
1294
  void CreateNeededAnonFlexOrGridItems(nsFrameConstructorState& aState,
1295
                                       FrameConstructionItemList& aItems,
1296
                                       nsIFrame* aParentFrame);
1297
1298
  enum RubyWhitespaceType
1299
  {
1300
    eRubyNotWhitespace,
1301
    eRubyInterLevelWhitespace,
1302
    // Includes inter-base and inter-annotation whitespace
1303
    eRubyInterLeafWhitespace,
1304
    eRubyInterSegmentWhitespace
1305
  };
1306
1307
  /**
1308
   * Function to compute the whitespace type according to the display
1309
   * values of the previous and the next elements.
1310
   */
1311
  static inline RubyWhitespaceType ComputeRubyWhitespaceType(
1312
    mozilla::StyleDisplay aPrevDisplay, mozilla::StyleDisplay aNextDisplay);
1313
1314
  /**
1315
   * Function to interpret the type of whitespace between
1316
   * |aStartIter| and |aEndIter|.
1317
   */
1318
  static inline RubyWhitespaceType InterpretRubyWhitespace(
1319
    nsFrameConstructorState& aState,
1320
    const FCItemIterator& aStartIter, const FCItemIterator& aEndIter);
1321
1322
  /**
1323
   * Function to wrap consecutive misparented inline content into
1324
   * a ruby base box or a ruby text box.
1325
   */
1326
  void WrapItemsInPseudoRubyLeafBox(FCItemIterator& aIter,
1327
                                    ComputedStyle* aParentStyle,
1328
                                    nsIContent* aParentContent);
1329
1330
  /**
1331
   * Function to wrap consecutive misparented items
1332
   * into a ruby level container.
1333
   */
1334
  inline void WrapItemsInPseudoRubyLevelContainer(
1335
    nsFrameConstructorState& aState, FCItemIterator& aIter,
1336
    ComputedStyle* aParentStyle, nsIContent* aParentContent);
1337
1338
  /**
1339
   * Function to trim leading and trailing whitespaces.
1340
   */
1341
  inline void TrimLeadingAndTrailingWhitespaces(
1342
    nsFrameConstructorState& aState, FrameConstructionItemList& aItems);
1343
1344
  /**
1345
   * Function to create internal ruby boxes.
1346
   */
1347
  inline void CreateNeededPseudoInternalRubyBoxes(
1348
    nsFrameConstructorState& aState,
1349
    FrameConstructionItemList& aItems, nsIFrame* aParentFrame);
1350
1351
  /**
1352
   * Function to create the pseudo intermediate containers we need.
1353
   * @param aItems the child frame construction items before pseudo creation
1354
   * @param aParentFrame the parent frame we're creating pseudos for
1355
   */
1356
  inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState,
1357
                                           FrameConstructionItemList& aItems,
1358
                                           nsIFrame* aParentFrame);
1359
1360
  /**
1361
   * Function to wrap consecutive items into a pseudo parent.
1362
   */
1363
  inline void WrapItemsInPseudoParent(nsIContent* aParentContent,
1364
                                      ComputedStyle* aParentStyle,
1365
                                      ParentType aWrapperType,
1366
                                      FCItemIterator& aIter,
1367
                                      const FCItemIterator& aEndIter);
1368
1369
  /**
1370
   * Function to create the pseudo siblings we need.
1371
   */
1372
  inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState,
1373
                                         FrameConstructionItemList& aItems,
1374
                                         nsIFrame* aParentFrame);
1375
1376
  /**
1377
   * Function to adjust aParentFrame to deal with captions.
1378
   * @param aParentFrame the frame we think should be the parent.  This will be
1379
   *        adjusted to point to the right parent frame.
1380
   * @param aFCData the FrameConstructionData that would be used for frame
1381
   *        construction.
1382
   * @param aComputedStyle the style for aChildContent
1383
   */
1384
  // XXXbz this function should really go away once we rework pseudo-frame
1385
  // handling to be better. This should simply be part of the job of
1386
  // GetGeometricParent, and stuff like the frameitems and parent frame should
1387
  // be kept track of in the state...
1388
  void AdjustParentFrame(nsContainerFrame**           aParentFrame,
1389
                         const FrameConstructionData* aFCData,
1390
                         ComputedStyle*              aComputedStyle);
1391
1392
  // END TABLE SECTION
1393
1394
protected:
1395
  static nsIFrame* CreatePlaceholderFrameFor(nsIPresShell*     aPresShell,
1396
                                             nsIContent*       aContent,
1397
                                             nsIFrame*         aFrame,
1398
                                             nsContainerFrame* aParentFrame,
1399
                                             nsIFrame*         aPrevInFlow,
1400
                                             nsFrameState      aTypeBit);
1401
1402
  static nsIFrame* CreateBackdropFrameFor(nsIPresShell* aPresShell,
1403
                                          nsIContent* aContent,
1404
                                          nsIFrame* aFrame,
1405
                                          nsContainerFrame* aParentFrame);
1406
1407
private:
1408
  // ConstructSelectFrame puts the new frame in aFrameItems and
1409
  // handles the kids of the select.
1410
  nsIFrame* ConstructSelectFrame(nsFrameConstructorState& aState,
1411
                                 FrameConstructionItem&   aItem,
1412
                                 nsContainerFrame*        aParentFrame,
1413
                                 const nsStyleDisplay*    aStyleDisplay,
1414
                                 nsFrameItems&            aFrameItems);
1415
1416
  // ConstructFieldSetFrame puts the new frame in aFrameItems and
1417
  // handles the kids of the fieldset
1418
  nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
1419
                                   FrameConstructionItem&   aItem,
1420
                                   nsContainerFrame*        aParentFrame,
1421
                                   const nsStyleDisplay*    aStyleDisplay,
1422
                                   nsFrameItems&            aFrameItems);
1423
1424
  // ConstructDetailsFrame puts the new frame in aFrameItems and
1425
  // handles the kids of the details.
1426
  nsIFrame* ConstructDetailsFrame(nsFrameConstructorState& aState,
1427
                                  FrameConstructionItem& aItem,
1428
                                  nsContainerFrame* aParentFrame,
1429
                                  const nsStyleDisplay* aStyleDisplay,
1430
                                  nsFrameItems& aFrameItems);
1431
1432
  void ConstructTextFrame(const FrameConstructionData* aData,
1433
                          nsFrameConstructorState& aState,
1434
                          nsIContent*              aContent,
1435
                          nsContainerFrame*        aParentFrame,
1436
                          ComputedStyle*          aComputedStyle,
1437
                          nsFrameItems&            aFrameItems);
1438
1439
  // If aPossibleTextContent is a text node and doesn't have a frame, append a
1440
  // frame construction item for it to aItems.
1441
  void AddTextItemIfNeeded(nsFrameConstructorState& aState,
1442
                           const InsertionPoint& aInsertion,
1443
                           nsIContent* aPossibleTextContent,
1444
                           FrameConstructionItemList& aItems);
1445
1446
  // If aContent is a text node and doesn't have a frame, try to create a frame
1447
  // for it.
1448
  void ReframeTextIfNeeded(nsIContent* aContent);
1449
1450
  void AddPageBreakItem(nsIContent* aContent,
1451
                        FrameConstructionItemList& aItems);
1452
1453
  // Function to find FrameConstructionData for aElement.  Will return
1454
  // null if aElement is not HTML.
1455
  // aParentFrame might be null.  If it is, that means it was an
1456
  // inline frame.
1457
  static const FrameConstructionData* FindHTMLData(const Element&,
1458
                                                   nsIFrame* aParentFrame,
1459
                                                   ComputedStyle&);
1460
  // HTML data-finding helper functions
1461
  static const FrameConstructionData* FindImgData(const Element&, ComputedStyle&);
1462
  static const FrameConstructionData* FindGeneratedImageData(const Element&, ComputedStyle&);
1463
  static const FrameConstructionData* FindImgControlData(const Element&, ComputedStyle&);
1464
  static const FrameConstructionData* FindInputData(const Element&, ComputedStyle&);
1465
  static const FrameConstructionData* FindObjectData(const Element&, ComputedStyle&);
1466
  static const FrameConstructionData* FindCanvasData(const Element&, ComputedStyle&);
1467
1468
  /* Construct a frame from the given FrameConstructionItem.  This function
1469
     will handle adding the frame to frame lists, processing children, setting
1470
     the frame as the primary frame for the item's content, and so forth.
1471
1472
     @param aItem the FrameConstructionItem to use.
1473
     @param aState the frame construction state to use.
1474
     @param aParentFrame the frame to set as the parent of the
1475
                         newly-constructed frame.
1476
     @param aFrameItems the frame list to add the new frame (or its
1477
                        placeholder) to.
1478
  */
1479
  void ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
1480
                                      nsFrameConstructorState& aState,
1481
                                      nsContainerFrame* aParentFrame,
1482
                                      nsFrameItems& aFrameItems);
1483
1484
  // possible flags for AddFrameConstructionItemInternal's aFlags argument
1485
  /* Allow xbl:base to affect the tag/namespace used. */
1486
0
#define ITEM_ALLOW_XBL_BASE 0x1
1487
  /* Allow page-break before and after items to be created if the
1488
     style asks for them. */
1489
0
#define ITEM_ALLOW_PAGE_BREAK 0x2
1490
  /* The item is a generated content item. */
1491
0
#define ITEM_IS_GENERATED_CONTENT 0x4
1492
  /* The item is within an SVG text block frame. */
1493
0
#define ITEM_IS_WITHIN_SVG_TEXT 0x8
1494
  /* The item allows items to be created for SVG <textPath> children. */
1495
0
#define ITEM_ALLOWS_TEXT_PATH_CHILD 0x10
1496
  /* The item is content created by an nsIAnonymousContentCreator frame */
1497
0
#define ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT 0x20
1498
  // The guts of AddFrameConstructionItems
1499
  // aParentFrame might be null.  If it is, that means it was an
1500
  // inline frame.
1501
  void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
1502
                                         nsIContent*              aContent,
1503
                                         nsContainerFrame*        aParentFrame,
1504
                                         bool                     aSuppressWhiteSpaceOptimizations,
1505
                                         ComputedStyle*           aComputedStyle,
1506
                                         uint32_t                 aFlags,
1507
                                         FrameConstructionItemList& aItems);
1508
1509
  /**
1510
   * Construct frames for the given item list and parent frame, and put the
1511
   * resulting frames in aFrameItems.
1512
   */
1513
  void ConstructFramesFromItemList(nsFrameConstructorState& aState,
1514
                                   FrameConstructionItemList& aItems,
1515
                                   nsContainerFrame* aParentFrame,
1516
                                   bool aParentIsWrapperAnonBox,
1517
                                   nsFrameItems& aFrameItems);
1518
  void ConstructFramesFromItem(nsFrameConstructorState& aState,
1519
                               FCItemIterator& aItem,
1520
                               nsContainerFrame* aParentFrame,
1521
                               nsFrameItems& aFrameItems);
1522
  static bool AtLineBoundary(FCItemIterator& aIter);
1523
1524
  nsresult GetAnonymousContent(nsIContent* aParent,
1525
                               nsIFrame* aParentFrame,
1526
                               nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
1527
1528
//MathML Mod - RBS
1529
  /**
1530
   * Takes the frames in aBlockItems and wraps them in a new anonymous block
1531
   * frame whose content is aContent and whose parent will be aParentFrame.
1532
   * The anonymous block is added to aNewItems and aBlockItems is cleared.
1533
   */
1534
  void FlushAccumulatedBlock(nsFrameConstructorState& aState,
1535
                             nsIContent* aContent,
1536
                             nsContainerFrame* aParentFrame,
1537
                             nsFrameItems& aBlockItems,
1538
                             nsFrameItems& aNewItems);
1539
1540
  // Function to find FrameConstructionData for an element.  Will return
1541
  // null if the element is not MathML.
1542
  static const FrameConstructionData* FindMathMLData(const Element&, ComputedStyle&);
1543
1544
  // Function to find FrameConstructionData for an element.  Will return
1545
  // null if the element is not XUL.
1546
  //
1547
  // NOTE(emilio): This gets the overloaded tag and namespace id since they can
1548
  // be overriden by extends="" in XBL.
1549
  static const FrameConstructionData* FindXULTagData(const Element&,
1550
                                                     nsAtom* aTag,
1551
                                                     ComputedStyle&);
1552
  // XUL data-finding helper functions and structures
1553
#ifdef MOZ_XUL
1554
  static const FrameConstructionData* FindPopupGroupData(const Element&, ComputedStyle&);
1555
  // sXULTextBoxData used for both labels and descriptions
1556
  static const FrameConstructionData sXULTextBoxData;
1557
  static const FrameConstructionData* FindXULLabelData(const Element&, ComputedStyle&);
1558
  static const FrameConstructionData* FindXULDescriptionData(const Element&, ComputedStyle&);
1559
#ifdef XP_MACOSX
1560
  static const FrameConstructionData* FindXULMenubarData(const Element&, ComputedStyle&);
1561
#endif /* XP_MACOSX */
1562
#endif /* MOZ_XUL */
1563
1564
  // Function to find FrameConstructionData for an element using one of the XUL
1565
  // display types.  Will return null if the style doesn't have a XUL display
1566
  // type.  This function performs no other checks, so should only be called if
1567
  // we know for sure that the element is not something that should get a frame
1568
  // constructed by tag.
1569
  static const FrameConstructionData* FindXULDisplayData(const nsStyleDisplay&,
1570
                                                         const Element&);
1571
1572
  /**
1573
   * Constructs an outer frame, an anonymous child that wraps its real
1574
   * children, and its descendant frames.  This is used by both ConstructOuterSVG
1575
   * and ConstructMarker, which both want an anonymous block child for their
1576
   * children to go in to.
1577
   */
1578
  nsContainerFrame* ConstructFrameWithAnonymousChild(
1579
                                  nsFrameConstructorState& aState,
1580
                                  FrameConstructionItem&   aItem,
1581
                                  nsContainerFrame*        aParentFrame,
1582
                                  nsFrameItems&            aFrameItems,
1583
                                  ContainerFrameCreationFunc aConstructor,
1584
                                  ContainerFrameCreationFunc aInnerConstructor,
1585
                                  nsICSSAnonBoxPseudo*     aInnerPseudo,
1586
                                  bool                     aCandidateRootFrame);
1587
1588
  /**
1589
   * Construct an nsSVGOuterSVGFrame.
1590
   */
1591
  nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
1592
                              FrameConstructionItem&   aItem,
1593
                              nsContainerFrame*        aParentFrame,
1594
                              const nsStyleDisplay*    aDisplay,
1595
                              nsFrameItems&            aFrameItems);
1596
1597
  /**
1598
   * Construct an nsSVGMarkerFrame.
1599
   */
1600
  nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
1601
                            FrameConstructionItem&   aItem,
1602
                            nsContainerFrame*        aParentFrame,
1603
                            const nsStyleDisplay*    aDisplay,
1604
                            nsFrameItems&            aFrameItems);
1605
1606
  static const FrameConstructionData* FindSVGData(const Element&,
1607
                                                  nsIFrame* aParentFrame,
1608
                                                  bool aIsWithinSVGText,
1609
                                                  bool aAllowsTextPathChild,
1610
                                                  ComputedStyle&);
1611
1612
  // Not static because it does PropagateScrollToViewport.  If this
1613
  // changes, make this static.
1614
  const FrameConstructionData* FindDisplayData(const nsStyleDisplay&,
1615
                                               const Element&);
1616
1617
  /**
1618
   * Construct a scrollable block frame
1619
   */
1620
  nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState,
1621
                                     FrameConstructionItem&   aItem,
1622
                                     nsContainerFrame*        aParentFrame,
1623
                                     const nsStyleDisplay*    aDisplay,
1624
                                     nsFrameItems&            aFrameItems);
1625
1626
  /**
1627
   * Construct a scrollable block frame using the given block frame creation
1628
   * function.
1629
   */
1630
  nsIFrame* ConstructScrollableBlockWithConstructor(
1631
    nsFrameConstructorState& aState,
1632
    FrameConstructionItem& aItem,
1633
    nsContainerFrame* aParentFrame,
1634
    const nsStyleDisplay* aDisplay,
1635
    nsFrameItems& aFrameItems,
1636
    BlockFrameCreationFunc aConstructor);
1637
1638
  /**
1639
   * Construct a non-scrollable block frame
1640
   */
1641
  nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState,
1642
                                        FrameConstructionItem&   aItem,
1643
                                        nsContainerFrame*        aParentFrame,
1644
                                        const nsStyleDisplay*    aDisplay,
1645
                                        nsFrameItems&            aFrameItems);
1646
1647
  /**
1648
   * Construct a non-scrollable block frame using the given block frame creation
1649
   * function.
1650
   */
1651
  nsIFrame* ConstructNonScrollableBlockWithConstructor(
1652
    nsFrameConstructorState& aState,
1653
    FrameConstructionItem& aItem,
1654
    nsContainerFrame* aParentFrame,
1655
    const nsStyleDisplay* aDisplay,
1656
    nsFrameItems& aFrameItems,
1657
    BlockFrameCreationFunc aConstructor);
1658
1659
  /**
1660
   * This adds FrameConstructionItem objects to aItemsToConstruct for the
1661
   * anonymous content returned by an nsIAnonymousContentCreator::
1662
   * CreateAnonymousContent implementation.
1663
   */
1664
  void AddFCItemsForAnonymousContent(
1665
            nsFrameConstructorState& aState,
1666
            nsContainerFrame* aFrame,
1667
            const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
1668
            FrameConstructionItemList& aItemsToConstruct,
1669
            uint32_t aExtraFlags = 0);
1670
1671
  /**
1672
   * Construct the frames for the children of aContent.  "children" is defined
1673
   * as "whatever FlattenedChildIterator returns for aContent".  This means we're
1674
   * basically operating on children in the "flattened tree" per sXBL/XBL2.
1675
   * This method will also handle constructing ::before, ::after,
1676
   * ::first-letter, and ::first-line frames, as needed and if allowed.
1677
   *
1678
   * If the parent is a float containing block, this method will handle pushing
1679
   * it as the float containing block in aState (so there's no need for callers
1680
   * to push it themselves).
1681
   *
1682
   * @param aState the frame construction state
1683
   * @param aContent the content node whose children need frames
1684
   * @param aComputedStyle the style for aContent
1685
   * @param aParentFrame the frame to use as the parent frame for the new in-flow
1686
   *        kids. Note that this must be its own content insertion frame, but
1687
   *        need not be be the primary frame for aContent.  This frame will be
1688
   *        pushed as the float containing block, as needed.  aFrame is also
1689
   *        used to find the parent style for the kids' style
1690
   *        (not necessary aFrame's style).
1691
   * @param aCanHaveGeneratedContent Whether to allow :before and
1692
   *        :after styles on the parent.
1693
   * @param aFrameItems the list in which we should place the in-flow children
1694
   * @param aAllowBlockStyles Whether to allow first-letter and first-line
1695
   *        styles on the parent.
1696
   * @param aPendingBinding Make sure to push this into aState before doing any
1697
   *        child item construction.
1698
   * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
1699
   *        test and the anonymous content creation.  If null, aFrame will be
1700
   *        used.
1701
   */
1702
  void ProcessChildren(nsFrameConstructorState& aState,
1703
                       nsIContent*              aContent,
1704
                       ComputedStyle*           aComputedStyle,
1705
                       nsContainerFrame*        aParentFrame,
1706
                       const bool               aCanHaveGeneratedContent,
1707
                       nsFrameItems&            aFrameItems,
1708
                       const bool               aAllowBlockStyles,
1709
                       PendingBinding*          aPendingBinding,
1710
                       nsIFrame*                aPossiblyLeafFrame = nullptr);
1711
1712
  /**
1713
   * These two functions are used when we start frame creation from a non-root
1714
   * element. They should recreate the same state that we would have
1715
   * arrived at if we had built frames from the root frame to aFrame.
1716
   * Therefore, any calls to PushFloatContainingBlock and
1717
   * PushAbsoluteContainingBlock during frame construction should get
1718
   * corresponding logic in these functions.
1719
   */
1720
public:
1721
  enum ContainingBlockType {
1722
    ABS_POS,
1723
    FIXED_POS
1724
  };
1725
  nsContainerFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame,
1726
                                               ContainingBlockType aType);
1727
  nsContainerFrame* GetFloatContainingBlock(nsIFrame* aFrame);
1728
1729
private:
1730
  // Build a scroll frame:
1731
  //  Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame.
1732
  // @param aNewFrame the created scrollframe --- output only
1733
  // @param aParentFrame the geometric parent that the scrollframe will have.
1734
  void
1735
  BuildScrollFrame(nsFrameConstructorState& aState,
1736
                   nsIContent*              aContent,
1737
                   ComputedStyle*           aContentStyle,
1738
                   nsIFrame*                aScrolledFrame,
1739
                   nsContainerFrame*        aParentFrame,
1740
                   nsContainerFrame*&       aNewFrame);
1741
1742
  // Builds the initial ScrollFrame
1743
  already_AddRefed<ComputedStyle>
1744
  BeginBuildingScrollFrame(nsFrameConstructorState& aState,
1745
                           nsIContent*              aContent,
1746
                           ComputedStyle*           aContentStyle,
1747
                           nsContainerFrame*        aParentFrame,
1748
                           nsAtom*                  aScrolledPseudo,
1749
                           bool                     aIsRoot,
1750
                           nsContainerFrame*&       aNewFrame);
1751
1752
  // Completes the building of the scrollframe:
1753
  // Creates a view for the scrolledframe and makes it the child of the scrollframe.
1754
  void
1755
  FinishBuildingScrollFrame(nsContainerFrame* aScrollFrame,
1756
                            nsIFrame* aScrolledFrame);
1757
1758
  // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false
1759
  // aBuildCombobox indicates if we are building a combobox that has a dropdown
1760
  // popup widget or not.
1761
  void
1762
  InitializeSelectFrame(nsFrameConstructorState& aState,
1763
                        nsContainerFrame*        aScrollFrame,
1764
                        nsContainerFrame*        aScrolledFrame,
1765
                        nsIContent*              aContent,
1766
                        nsContainerFrame*        aParentFrame,
1767
                        ComputedStyle*           aComputedStyle,
1768
                        bool                     aBuildCombobox,
1769
                        PendingBinding*          aPendingBinding,
1770
                        nsFrameItems&            aFrameItems);
1771
1772
1773
  /**
1774
   * Recreate frames for aContent.
1775
   * @param aContent the content to recreate frames for
1776
   * @param aFlags normally you want to pass REMOVE_FOR_RECONSTRUCTION here
1777
   */
1778
  void RecreateFramesForContent(nsIContent*   aContent,
1779
                                InsertionKind aInsertionKind);
1780
1781
  /**
1782
   *  Handles change of rowspan and colspan attributes on table cells.
1783
   */
1784
  void UpdateTableCellSpans(nsIContent* aContent);
1785
1786
  // If removal of aFrame from the frame tree requires reconstruction of some
1787
  // containing block (either of aFrame or of its parent) due to {ib} splits or
1788
  // table pseudo-frames, recreate the relevant frame subtree.  The return value
1789
  // indicates whether this happened.  aFrame must be the result of a
1790
  // GetPrimaryFrame() call on a content node (which means its parent is also
1791
  // not null).
1792
  bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame);
1793
1794
  nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell*     aPresShell,
1795
                                            nsPresContext*    aPresContext,
1796
                                            nsIFrame*         aFrame,
1797
                                            nsContainerFrame* aParentFrame,
1798
                                            nsIContent*       aContent,
1799
                                            ComputedStyle*    aComputedStyle);
1800
1801
  nsIFrame* CreateContinuingTableFrame(nsIPresShell*     aPresShell,
1802
                                       nsIFrame*         aFrame,
1803
                                       nsContainerFrame* aParentFrame,
1804
                                       nsIContent*       aContent,
1805
                                       ComputedStyle*    aComputedStyle);
1806
1807
  //----------------------------------------
1808
1809
  // Methods support creating block frames and their children
1810
1811
  already_AddRefed<ComputedStyle>
1812
  GetFirstLetterStyle(nsIContent* aContent, ComputedStyle* aComputedStyle);
1813
1814
  already_AddRefed<ComputedStyle>
1815
  GetFirstLineStyle(nsIContent* aContent, ComputedStyle* aComputedStyle);
1816
1817
  bool ShouldHaveFirstLetterStyle(nsIContent* aContent,
1818
                                  ComputedStyle* aComputedStyle);
1819
1820
  // Check whether a given block has first-letter style.  Make sure to
1821
  // only pass in blocks!  And don't pass in null either.
1822
  bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
1823
1824
  bool ShouldHaveFirstLineStyle(nsIContent* aContent,
1825
                                ComputedStyle* aComputedStyle);
1826
1827
  void ShouldHaveSpecialBlockStyle(nsIContent*    aContent,
1828
                                   ComputedStyle* aComputedStyle,
1829
                                   bool*          aHaveFirstLetterStyle,
1830
                                   bool*          aHaveFirstLineStyle);
1831
1832
1833
  // Initialize aBlockFrame, and wrap it in a ColumnSetFrame if needed.
1834
  //
1835
  // If a ColumnSetFrame needs to be created, then this function will create
1836
  // one, and set aBlockFrame as its child (with an updated "columnContent"
1837
  // ComputedStyle() pointer), and initialize both frames. Otherwise, it
1838
  // initializes aBlockFrame.
1839
  //
1840
  // @return the new ColumnSetFrame if needed; otherwise aBlockFrame.
1841
  nsContainerFrame* InitAndWrapInColumnSetFrameIfNeeded(
1842
    nsFrameConstructorState& aState,
1843
    nsIContent* aContent,
1844
    nsContainerFrame* aParentFrame,
1845
    nsContainerFrame* aBlockFrame,
1846
    ComputedStyle* aComputedStyle);
1847
1848
  // |aContentParentFrame| should be null if it's really the same as
1849
  // |aParentFrame|.
1850
  // @param aFrameItems where we want to put the block in case it's in-flow.
1851
  // @param aNewFrame an in/out parameter. On input it is the block to be
1852
  // constructed. On output it is reset to the outermost
1853
  // frame constructed (e.g. if we need to wrap the block in an
1854
  // nsColumnSetFrame.
1855
  // @param aParentFrame is the desired parent for the (possibly wrapped)
1856
  // block
1857
  // @param aContentParent is the parent the block would have if it
1858
  // were in-flow
1859
  // @param aPositionedFrameForAbsPosContainer if non-null, then the new
1860
  // block should be an abs-pos container and aPositionedFrameForAbsPosContainer
1861
  // is the frame whose style is making this block an abs-pos container.
1862
  // @param aPendingBinding the pending binding  from this block's frame
1863
  // construction item.
1864
  void ConstructBlock(nsFrameConstructorState& aState,
1865
                      nsIContent*              aContent,
1866
                      nsContainerFrame*        aParentFrame,
1867
                      nsContainerFrame*        aContentParentFrame,
1868
                      ComputedStyle*           aComputedStyle,
1869
                      nsContainerFrame**       aNewFrame,
1870
                      nsFrameItems&            aFrameItems,
1871
                      nsIFrame*                aPositionedFrameForAbsPosContainer,
1872
                      PendingBinding*          aPendingBinding);
1873
1874
  nsIFrame* ConstructInline(nsFrameConstructorState& aState,
1875
                            FrameConstructionItem&   aItem,
1876
                            nsContainerFrame*        aParentFrame,
1877
                            const nsStyleDisplay*    aDisplay,
1878
                            nsFrameItems&            aFrameItems);
1879
1880
  /**
1881
   * Create any additional {ib} siblings needed to contain aChildItems and put
1882
   * them in aSiblings.
1883
   *
1884
   * @param aState the frame constructor state
1885
   * @param aInitialInline is an already-existing inline frame that will be
1886
   *                       part of this {ib} split and come before everything
1887
   *                       in aSiblings.
1888
   * @param aIsPositioned true if aInitialInline is positioned.
1889
   * @param aChildItems is a child list starting with a block; this method
1890
   *                    assumes that the inline has already taken all the
1891
   *                    children it wants.  When the method returns aChildItems
1892
   *                    will be empty.
1893
   * @param aSiblings the nsFrameItems to put the newly-created siblings into.
1894
   *
1895
   * This method is responsible for making any SetFrameIsIBSplit calls that are
1896
   * needed.
1897
   */
1898
  void CreateIBSiblings(nsFrameConstructorState& aState,
1899
                        nsContainerFrame* aInitialInline,
1900
                        bool aIsPositioned,
1901
                        nsFrameItems& aChildItems,
1902
                        nsFrameItems& aSiblings);
1903
1904
  /**
1905
   * For an inline aParentItem, construct its list of child
1906
   * FrameConstructionItems and set its mIsAllInline flag appropriately.
1907
   */
1908
  void BuildInlineChildItems(nsFrameConstructorState& aState,
1909
                             FrameConstructionItem& aParentItem,
1910
                             bool aItemIsWithinSVGText,
1911
                             bool aItemAllowsTextPathChild);
1912
1913
  // Determine whether we need to wipe out what we just did and start over
1914
  // because we're doing something like adding block kids to an inline frame
1915
  // (and therefore need an {ib} split).  aPrevSibling must be correct, even in
1916
  // aIsAppend cases.  Passing aIsAppend false even when an append is happening
1917
  // is ok in terms of correctness, but can lead to unnecessary reframing.  If
1918
  // aIsAppend is true, then the caller MUST call
1919
  // nsCSSFrameConstructor::AppendFramesToParent (as opposed to
1920
  // nsFrameManager::InsertFrames directly) to add the new frames.
1921
  // @return true if we reconstructed the containing block, false
1922
  // otherwise
1923
  bool WipeContainingBlock(nsFrameConstructorState& aState,
1924
                           nsIFrame* aContainingBlock,
1925
                           nsIFrame* aFrame,
1926
                           FrameConstructionItemList& aItems,
1927
                           bool aIsAppend,
1928
                           nsIFrame* aPrevSibling);
1929
1930
  void ReframeContainingBlock(nsIFrame* aFrame);
1931
1932
  //----------------------------------------
1933
1934
  // Methods support :first-letter style
1935
1936
  nsFirstLetterFrame*
1937
  CreateFloatingLetterFrame(nsFrameConstructorState& aState,
1938
                            nsIContent*              aTextContent,
1939
                            nsIFrame*                aTextFrame,
1940
                            nsContainerFrame*        aParentFrame,
1941
                            ComputedStyle*           aParentComputedStyle,
1942
                            ComputedStyle*           aComputedStyle,
1943
                            nsFrameItems&            aResult);
1944
1945
  void CreateLetterFrame(nsContainerFrame*        aBlockFrame,
1946
                         nsContainerFrame*        aBlockContinuation,
1947
                         nsIContent*              aTextContent,
1948
                         nsContainerFrame*        aParentFrame,
1949
                         nsFrameItems&            aResult);
1950
1951
  void WrapFramesInFirstLetterFrame(nsContainerFrame* aBlockFrame,
1952
                                    nsFrameItems&     aBlockFrames);
1953
1954
  /**
1955
   * Looks in the block aBlockFrame for a text frame that contains the
1956
   * first-letter of the block and creates the necessary first-letter frames
1957
   * and returns them in aLetterFrames.
1958
   *
1959
   * @param aBlockFrame the (first-continuation of) the block we are creating a
1960
   *                    first-letter frame for
1961
   * @param aBlockContinuation the current continuation of the block that we
1962
   *                           are looking in for a textframe with suitable
1963
   *                           contents for first-letter
1964
   * @param aParentFrame the current frame whose children we are looking at for
1965
   *                     a suitable first-letter textframe
1966
   * @param aParentFrameList the first child of aParentFrame
1967
   * @param aModifiedParent returns the parent of the textframe that contains
1968
   *                        the first-letter
1969
   * @param aTextFrame returns the textframe that had the first-letter
1970
   * @param aPrevFrame returns the previous sibling of aTextFrame
1971
   * @param aLetterFrames returns the frames that were created
1972
   */
1973
  void WrapFramesInFirstLetterFrame(nsContainerFrame*  aBlockFrame,
1974
                                    nsContainerFrame*  aBlockContinuation,
1975
                                    nsContainerFrame*  aParentFrame,
1976
                                    nsIFrame*          aParentFrameList,
1977
                                    nsContainerFrame** aModifiedParent,
1978
                                    nsIFrame**         aTextFrame,
1979
                                    nsIFrame**         aPrevFrame,
1980
                                    nsFrameItems&      aLetterFrames,
1981
                                    bool*              aStopLooking);
1982
1983
  void RecoverLetterFrames(nsContainerFrame* aBlockFrame);
1984
1985
  //
1986
  void RemoveLetterFrames(nsIPresShell*     aPresShell,
1987
                          nsContainerFrame* aBlockFrame);
1988
1989
  // Recursive helper for RemoveLetterFrames
1990
  void RemoveFirstLetterFrames(nsIPresShell*     aPresShell,
1991
                               nsContainerFrame* aFrame,
1992
                               nsContainerFrame* aBlockFrame,
1993
                               bool*             aStopLooking);
1994
1995
  // Special remove method for those pesky floating first-letter frames
1996
  void RemoveFloatingFirstLetterFrames(nsIPresShell*    aPresShell,
1997
                                       nsIFrame*        aBlockFrame);
1998
1999
  // Capture state for the frame tree rooted at the frame associated with the
2000
  // content object, aContent
2001
  void CaptureStateForFramesOf(nsIContent* aContent,
2002
                               nsILayoutHistoryState* aHistoryState);
2003
2004
  //----------------------------------------
2005
2006
  // Methods support :first-line style
2007
2008
  // This method chops the initial inline-outside frames out of aFrameItems.
2009
  // If aLineFrame is non-null, it appends them to that frame.  Otherwise, it
2010
  // creates a new line frame, sets the inline frames as its initial child
2011
  // list, and inserts that line frame at the front of what's left of
2012
  // aFrameItems.  In both cases, the kids are reparented to the line frame.
2013
  // After this call, aFrameItems holds the frames that need to become kids of
2014
  // the block (possibly including line frames).
2015
  void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
2016
                                  nsIContent*              aBlockContent,
2017
                                  nsContainerFrame*        aBlockFrame,
2018
                                  nsFirstLineFrame*        aLineFrame,
2019
                                  nsFrameItems&            aFrameItems);
2020
2021
  // Handle the case when a block with first-line style is appended to (by
2022
  // possibly calling WrapFramesInFirstLineFrame as needed).
2023
  void AppendFirstLineFrames(nsFrameConstructorState& aState,
2024
                             nsIContent*              aContent,
2025
                             nsContainerFrame*        aBlockFrame,
2026
                             nsFrameItems&            aFrameItems);
2027
2028
  /**
2029
   * When aFrameItems is being inserted into aParentFrame, and aParentFrame has
2030
   * pseudo-element-affected styles, it's possible that we're inserting under a
2031
   * ::first-line frame.  In that case, with servo's style system, the styles we
2032
   * resolved for aFrameItems are wrong (they don't take ::first-line into
2033
   * account), and we should fix them up, which is what this method does.
2034
   *
2035
   * This method does not mutate aFrameItems.
2036
   */
2037
  void CheckForFirstLineInsertion(nsIFrame* aParentFrame,
2038
                                  nsFrameItems& aFrameItems);
2039
2040
  /**
2041
   * Find the next frame for appending to a given insertion point.
2042
   *
2043
   * We're appending, so this is almost always null, except for a few edge
2044
   * cases.
2045
   */
2046
  nsIFrame* FindNextSiblingForAppend(const InsertionPoint&);
2047
2048
  // The direction in which we should look for siblings.
2049
  enum class SiblingDirection
2050
  {
2051
    Forward,
2052
    Backward,
2053
  };
2054
2055
  /**
2056
   * Find the frame for the content immediately next to the one aIter points to,
2057
   * in the direction SiblingDirection indicates, following continuations if
2058
   * necessary.
2059
   *
2060
   * aIter is passed by const reference on purpose, so as not to modify the
2061
   * caller's iterator.
2062
   *
2063
   * @param aIter should be positioned such that aIter.GetPreviousChild()
2064
   *          is the first content to search for frames
2065
   * @param aTargetContentDisplay the CSS display enum for the content aIter
2066
   *          points to if already known. It will be filled in if needed.
2067
   */
2068
  template<SiblingDirection>
2069
  nsIFrame* FindSibling(const mozilla::dom::FlattenedChildIterator& aIter,
2070
                        mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2071
2072
  // Helper for the implementation of FindSibling.
2073
  //
2074
  // Beware that this function does mutate the iterator.
2075
  template<SiblingDirection>
2076
  nsIFrame* FindSiblingInternal(
2077
    mozilla::dom::FlattenedChildIterator&,
2078
    nsIContent* aTargetContent,
2079
    mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2080
2081
  // An alias of FindSibling<SiblingDirection::Forward>.
2082
  nsIFrame* FindNextSibling(const mozilla::dom::FlattenedChildIterator& aIter,
2083
                            mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2084
  // An alias of FindSibling<SiblingDirection::Backwards>.
2085
  nsIFrame* FindPreviousSibling(const mozilla::dom::FlattenedChildIterator& aIter,
2086
                                mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2087
2088
  // Given a potential first-continuation sibling frame for aTargetContent,
2089
  // verify that it is an actual valid sibling for it, and return the
2090
  // appropriate continuation the new frame for aTargetContent should be
2091
  // inserted next to.
2092
  nsIFrame* AdjustSiblingFrame(nsIFrame* aSibling,
2093
                               nsIContent* aTargetContent,
2094
                               mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay,
2095
                               SiblingDirection aDirection);
2096
2097
  // Find the right previous sibling for an insertion.  This also updates the
2098
  // parent frame to point to the correct continuation of the parent frame to
2099
  // use, and returns whether this insertion is to be treated as an append.
2100
  // aChild is the child being inserted.
2101
  // aIsRangeInsertSafe returns whether it is safe to do a range insert with
2102
  // aChild being the first child in the range. It is the callers'
2103
  // responsibility to check whether a range insert is safe with regards to
2104
  // fieldsets.
2105
  // The skip parameters are used to ignore a range of children when looking
2106
  // for a sibling. All nodes starting from aStartSkipChild and up to but not
2107
  // including aEndSkipChild will be skipped over when looking for sibling
2108
  // frames. Skipping a range can deal with XBL but not when there are multiple
2109
  // insertion points.
2110
  nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion, // inout
2111
                                    nsIContent* aChild,
2112
                                    bool* aIsAppend,
2113
                                    bool* aIsRangeInsertSafe,
2114
                                    nsIContent* aStartSkipChild = nullptr,
2115
                                    nsIContent *aEndSkipChild = nullptr);
2116
2117
  // see if aContent and aSibling are legitimate siblings due to restrictions
2118
  // imposed by table columns
2119
  // XXXbz this code is generally wrong, since the frame for aContent
2120
  // may be constructed based on tag, not based on aDisplay!
2121
  bool IsValidSibling(nsIFrame*              aSibling,
2122
                      nsIContent*            aContent,
2123
                      mozilla::Maybe<mozilla::StyleDisplay>& aDisplay);
2124
2125
  void QuotesDirty();
2126
  void CountersDirty();
2127
2128
  // Create touch caret frame.
2129
  void ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
2130
                                          nsIFrame* aFrame,
2131
                                          nsIContent* aDocElement);
2132
2133
public:
2134
2135
  friend class nsFrameConstructorState;
2136
2137
private:
2138
  // For allocating FrameConstructionItems from the mFCItemPool arena.
2139
  friend struct FrameConstructionItem;
2140
  void* AllocateFCItem();
2141
  void FreeFCItem(FrameConstructionItem*);
2142
2143
  nsIDocument*        mDocument;  // Weak ref
2144
2145
  // See the comment at the start of ConstructRootFrame for more details
2146
  // about the following frames.
2147
2148
  // This is just the outermost frame for the root element.
2149
  nsContainerFrame*   mRootElementFrame;
2150
  // This is the frame for the root element that has no pseudo-element style.
2151
  nsIFrame*           mRootElementStyleFrame;
2152
  // This is the containing block that contains the root element ---
2153
  // the real "initial containing block" according to CSS 2.1.
2154
  nsContainerFrame*   mDocElementContainingBlock;
2155
  nsIFrame*           mPageSequenceFrame;
2156
2157
  // FrameConstructionItem arena + list of freed items available for re-use.
2158
  mozilla::ArenaAllocator<4096, 8> mFCItemPool;
2159
  struct FreeFCItemLink { FreeFCItemLink* mNext; };
2160
  FreeFCItemLink* mFirstFreeFCItem;
2161
  size_t mFCItemsInUse;
2162
2163
  nsQuoteList         mQuoteList;
2164
  nsCounterManager    mCounterManager;
2165
  // Current ProcessChildren depth.
2166
  uint16_t            mCurrentDepth;
2167
  bool                mQuotesDirty : 1;
2168
  bool                mCountersDirty : 1;
2169
  bool                mIsDestroyingFrameTree : 1;
2170
  // This is true if mDocElementContainingBlock supports absolute positioning
2171
  bool                mHasRootAbsPosContainingBlock : 1;
2172
  bool                mAlwaysCreateFramesForIgnorableWhitespace : 1;
2173
2174
  nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
2175
};
2176
2177
#endif /* nsCSSFrameConstructor_h___ */