We were neglecting to resolve the used horizontal padding and border
properties on block-level boxes when treating their width as `auto`
during intrinsic sizing.
This led to padding and border not contributing to the intrinsic width
of their containing block
Calling parent_context_did_dimension_child_root_box immediately after
laying out the inside of the floating box is not correct, as we haven't
worked out the dimensions of the floating box yet.
In particular, this caused the icons in the top bar of Cookie Clicker
to not hug the top of the viewport. This is because the icons are
absolutely positioned elements inside a floating element which has
padding applied to it. Since we laid out the abspos element before
the floating element, it got padding values of 0 from the parent, the
default value, meaning it didn't take away the padding of it's floating
parent.
This follows how abspos boxes layout their inside boxes as well.
We were mistakenly creating stacking contexts for all elements with
non-static CSS position.
For `absolute` and `relative`, we should only create stacking contexts
if the `z-index` value is something other than `auto`.
This makes it possible to click the cookie on Cookie Clicker. :^)
It's not safe to unregister ImageBox from the browsing context in the
destructor (since the browsing context may have already been swept and
destroyed).
Now that both the layout tree and browsing context are GC-allocated,
we can formalize their relationship a bit better by having layout
nodes keep a NonnullGCPtr to the browsing context.
This makes the previously-indirect link direct, removing an unpleasant
"how do we know the browsing context is alive" question when accessing
it from the layout tree.
This removes a set of complex reference cycles between DOM, layout tree
and browsing context.
It also makes lifetimes much easier to reason about, as the DOM and
layout trees are now free to keep each other alive.
Instead of storing two JS::Handles into the DOM, we can combine them
into a single one.
If the layout node is anonymous, m_dom_node points to the DOM::Document.
Otherwise, m_dom_node points to the associated DOM node.
The anonymous state is moved to an m_anonymous boolean member.
This cuts the number of JS::Handles created by the layout tree in half
(and shrinks Layout::Node by 8 bytes).
When sizing grid children we now also check whether
calculate_min_content_height() adds to the computed height. Previously
we were using the result of layout_inner() which led to zero height of
not specifically sized block level children.
This fixes a height issue with our GitHub page. The footer is now at
its place and is not hovering over other content anymore.
Add classes ExplicitTrackSizing and MetaGridTrackSize which will allow
for managing properties like auto-fill and minmax.
In the following CSS example there are 3 classes that will be used:
grid-template-column: repeat(auto-fill, minmax(50px, 1fr) 75px);
ExplicitTrackSizing - will contain the entire value. e.g.
repeat(auto-fill, minmax(50px, 1fr) 75px)
With a flag if it's a repeat, as well as references to the
MetaGridTrackSizes which is the next step down.
MetaGridTrackSize:
Contain the individual grid track sizes. Here there are two:
minmax(50px, 1fr) as well as 75px.
This way can keep track if it's a minmax function or not, and the
references to both GridTrackSizes in the case it is, or in just the one
if it is not.
GridTrackSize:
Is the most basic element, in this case there are three in total; two of
which are held by the first MetaGridTrackSize, and the third is held by
the second MetaGridTrackSize.
Examples: 50px, 1fr and 75px.
As it turns out, we sometimes query the intrinsic height of a box before
having fully resolved and/or constrained its containing block. Because
of this, we may enter intrinsic sizing with different amounts of
available width for the same box.
To accommodate this scenario, we now allow caching of multiple intrinsic
heights, separated by the amount of available width provided as input.
This colors a bit outside the lines of the specification, but the spec
doesn't offer a proper explanation for how descendants of a flex item
are supposed to have access to the flex item's main size for purposes
of percentage resolution.
The approach I came up with here was to take the hypothetical main size
of each flex item, and assign it as a temporary main size. This allows
percentage resolution in descendants to work against the pre-flexing
main size of items. This seems to match how other engines behave,
although it feels somewhat dirty. If/when we learn more about this,
we can come up with something nicer.
We were using the available space in place of the stretch-fit size.
This was an oversight, and this patch fixes that. It's very possible
that this will uncover broken behavior elsewhere.
This property tells us how to lay out multi-line flex containers.
I implemented all modes except `space-between` and `space-around`.
Those are left as FIXMEs.
This ensures that we create a line box for content:"", which would
otherwise get pruned by the empty line cleanup in IFC.
The empty line box is important in this case, since it gives us a
reference point for measuring the automatic height of the IFC's
containing block. By having an empty line, we can now correctly measure
the impact of vertical margins on a generated box with content:""
and allow them to contribute to the block height.
When checking if a line box fragment "isn't just dumb inline content",
we were checking "is replaced or inline-block". What we really need to
be checking is "is replaced or inline-outside-but-not-flow-inside".
So now we check that.
This fixes an issue where inline-flex boxes were given incorrect extra
height due to being treated as regular text for purposes of line height
calculation.
Percentage heights are now considered definite when their containing
block has a definite height. This makes profile pictures have geometry
on Twitter. (We still don't load the images themselves though.)
This refactors the solve_for_{top, bottom, height, etc} lambdas to use a
common solve_for lambda that takes the length to be solved as an
argument. This way some code duplication is removed.
This patch implements the full "old model" height algorithm from the
CSS Positioned Layout spec. I went with the old model since we don't
yet have the machinery required to implement the new model.
Also, the width calculations already follow the old model, so this
is symmetric with that. Eventually we should of course implement the new
positioned layout model.
Now that intrinsic heights (correctly) depend on the amount of available
width, we can't just cache the first calculated min-content and
max-content heights and reuse it without thinking.
Instead, we have to cache three pairs:
- min-content & max-content height with definite available width
- min-content & max-content height with min-content available width
- min-content & max-content height with max-content available width
There might be some more elegant way of solving this, but basically this
makes the cache work correctly when someone's containing block is being
sized under a width constraint.
We were incorrectly resolving them against the available width, which
may or may not be the same as the containing block width.
The specification for these properties says that percentages resolve
against the containing block width, so that's what we should do.
When calculating the fit-content width or height for a flex item, we
need to use the available space *outside* the item, not the available
space *inside*.
We now know exactly how to calculate the min-content cross size for
multi-line flex containers, which is great. The other three intrinsic
constraints still fall back to the old ad-hoc code path.
5630e7b064
When the indicated column-span is greater than the implicit grid (like
in cases when the grid has the default size of 1x1, and the column is
supposed to span any number greater than that), then previously were
crashing.
Fixes a bug in the maybe_add_column() implementation of the
OccupationGrid. Previously were checking for the width of the grid based
off of the first row, and so when augmenting the column count row-by-row
the latter rows would have differing column counts.
Also, were doing an unnecessary + 1 which I imagine comes from before
when I wasn't quite clear on whether I was referring to columns by
index or by the css-value of the column (column 1 in the css is
column index 0).
For percentage cross min/max sizes that resolve against indefinite
available space, we now essentially ignore them instead of resolving
them to 0 at the start of layout.
Yet another legacy "is inline-block?" condition was causing us to insert
inline nodes directly as children of inline-flex containers (instead of
wrapping them in anonymous blocks, which would then cause them to become
flex items.)