Move the layout tree from GC allocation to refcounted ownership so
removed layout and paint subtrees are destroyed synchronously instead
of waiting for the next GC sweep. This dramatically reduces GC memory
usage peaks after layout tree churn and makes it easier for memory use
to fall back after large document updates.
Update layout factories, tree traversal, SVG layout node creation,
paintable back-pointers, and pseudo-element layout links to use RefPtr
ownership.
Make display: contents follow the same shape as Blink and WebKit: the
element itself does not create a layout node, and its children are
flattened into the nearest layout parent. Wrap direct non-whitespace
text in an anonymous inline node when the boxless element contributes
inherited style to that text.
Use an internal inline wrapper for display: contents pseudo-elements
so generated content can still participate in layout, painting, hit
testing, and pseudo-element queries. Keep CSSOM reporting the computed
display value from the pseudo style, not the internal wrapper.
Remove the retained out-of-tree layout node list and its testing hook,
since the flattened model does not need a side owner for boxless
elements. Add coverage for inherited text style, dynamic insertion
order, pseudo-element hit testing, and computed style queries.
Move ComputedProperties and CascadedProperties out of the GC. They no
longer contain strong references to GC-managed data.
Keep computed styles alive from DOM elements and animation updates with
RefPtr. Pass style into layout constructors by reference, since layout
only copies the values it needs while building nodes.
Use GC::Weak for cascade source links, so entries no longer keep the
style declaration or shadow root alive.
The Paintable tree and its supplemental painting data structures were
GC allocated because that was the easiest way to manage it and avoid
leaks introduced by ref cycles. This included the Paintable subclasses
themselves plus StackingContext, ChromeWidget, Scrollbar, ResizeHandle,
and scroll-frame state.
We are now trying to reduce GC allocation churn on layout and painting
updates, so keeping this short-lived rendering tree outside the JS heap
is a better fit. Move Paintable to RefCountedTreeNode, make painting
helpers ref-counted or weakly reference Paintables, and update the
layout and event-handler call sites to use RefPtr/WeakPtr ownership.
Instead, compute them on demand. This affects ReplacedBox and its
subclasses.
This commit is centered around a new Box::auto_content_box_size
method. It returns a SizeWithAspectRatio representing the natural
size of a replaced element, or the size derived from attributes
for text input and textarea. These values are used when the
corresponding axis is auto or indefinite.
Although introducing this API choke-point for sizing replaced and
replaced-like elements was the main goal, it's notable that layout
becomes more robust in the face of dynamic changes due to reduced
potential for stale size values (at the cost of extra calculations
and allocations).
This ensures that we are explicitly declaring the allocator to use when
allocating a cell(-inheriting) type, instead of silently falling back
to size-based allocation.
Since this is done in allocate_cell, this will only be detected for
types that are actively being allocated. However, since that means
they're _not_ being allocated, that means it's safe to not declare
an allocator to use for those. For example, the base TypedArray<T>,
which is never directly allocated and only the defined specializations
are ever allocated.
Instead of indiscriminately clearing the cache for all anonymous boxes,
we now only clear it for those that were generated by a non-anonymous
box in need of layout update.
This increases the cache hit rate and allows us to avoid more work.
Allows us to avoid DOM node lookup whenever we need to query natural
size of a box during layout.
Makes 3-4% of `Box::preferred_aspect_ratio()` go away from profiles on
www.nyan.cat
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:
* JS::NonnullGCPtr -> GC::Ref
* JS::GCPtr -> GC::Ptr
* JS::HeapFunction -> GC::Function
* JS::CellImpl -> GC::Cell
* JS::Handle -> GC::Root
Instead of storing them as CSS::Lengths, we now store the resolved
values for margin/padding/border/offset top/right/bottom/left with
each Layout::NodeWithStyleAndBoxModelMetrics.
This simplifies a lot of code since it's no longer necessary to
resolve values before using them.
Within the same stacking context, positioned elements must be painted
after non-positioned ones.
I added a Layout::Node::for_each_child_in_paint_order() to help with
this since it's also needed for hit testing.
Instead of doing a CSS property lookup for the line style of each
border edge during paint, we now cache the final CSS::LineStyle to use
in the Layout::BorderData.
Bring the names of various boxes closer to spec language. This should
hopefully make things easier to understand and hack on. :^)
Some notable changes:
- LayoutNode -> Layout::Node
- LayoutBox -> Layout::Box
- LayoutBlock -> Layout::BlockBox
- LayoutReplaced -> Layout::ReplacedBox
- LayoutDocument -> Layout::InitialContainingBlockBox
- LayoutText -> Layout::TextNode
- LayoutInline -> Layout::InlineNode
Note that this is not strictly a "box tree" as we also hang inline/text
nodes in the same tree, and they don't generate boxes. (Instead, they
contribute line box fragments to their containing block!)
2020-11-22 15:56:27 +01:00
Renamed from Libraries/LibWeb/Layout/LayoutBox.cpp (Browse further)