This is defined in the spec, but was missing in our table. Fix this, and
add a spec comment for what is missing. Also begin a basic text based
test for URL, so we can get some coverage of LibWeb's usage of URL too.
This takes the previous alternation optimisation and applies it to all
the alternation blocks instead of just the few instructions at the
start.
By generating a trie of instructions, all logically equivalent
instructions will be consolidated into a single node, allowing the
engine to avoid checking the same thing multiple times.
For instance, given the pattern /abc|ac|ab/, this optimisation would
generate the following tree:
- a
| - b
| | - c
| | | - <accept>
| | - <accept>
| - c
| | - <accept>
which will attempt to match 'a' or 'b' only once, and would also limit
the number of backtrackings performed in case alternatives fails to
match.
This optimisation is currently gated behind a simple cost model that
estimates the number of instructions generated, which is pessimistic for
small patterns, though the change in performance in such patterns is not
particularly large.
In order to follow spec text to achieve this, we need to change the
underlying representation of a host in AK::URL to deserialized format.
Before this, we were parsing the host and then immediately serializing
it again.
Making that change resulted in a whole bunch of fallout.
After this change, callers can access the serialized data through
this concept-host-serializer. The functional end result of this
change is that IPv6 hosts are now correctly serialized to be
surrounded with '[' and ']'.
Previously, we always rounded border-widths up when converting them to
device pixels. However, the spec asks us to follow a specific algorithm
to "snap" these values, so that the computed value is snapped.
The difference from before, is that widths of between 0 and 1 device
pixels are rounded up to 1, and and values larger than 1 are rounded
down.
If a math function resolves to `<length>` or `<percentage>`, then it
will by definition also resolve to `<length-percentage>`. (Same for any
other basic types.) Since we were checking `<length-percentage>` first
and then bailing if no given properties could accept that, math
functions would always fail to match a property that just accepts a non
`-percentage` type.
Multiple patches may be concatenated in the same patch file, such as git
commits which are changing multiple files at the same time. To handle
this, parse each patch in order in the patch file, and apply each patch
sequentially.
To determine whether we are at the end of a patch (and not just parsing
another hunk) the parser will look for a leading '@@ ' after every hunk.
If that is found, there is another hunk. Otherwise, we must be at the
end of this patch.
Previously patch would always expect the file that it was patching to
exist (even it were empty). If we know that the patch is creating a file
from nothing (i.e has a start line of '0'), then we treat a file that
doesn't exist as if it has no content lines.
Implement the patch '-p' / '--strip' option, which strips the given
number of leading components from filenames parsed in the patch header.
If not given this option defaults to the basename of that path.
This is a universal value like `initial` and `inherit` and works by
reverting the current value to whatever we had at the start of the
current cascade origin.
The implementation is somewhat inefficient as we make a copy of all
current values at the start of each origin. I'm sure we can come up with
a way to make this faster eventually.
Allow the left margin of a box which creates a block formatting context
to overlap with left floating boxes which are siblings in the document
tree.
Fixes#20233 and the comment layout on https://lobste.rs.
This change makes tree builder omit elements with "display: contents"
from the layout tree during construction. Their child elements are
instead directly appended to the parent element in layout tree.
Similar to commit 0652cc4, we now generate 2-stage lookup tables for
case conversion information. Only about 1500 code points are actually
cased. This means that case information is rather highly compressible,
as the blocks we break the code points into will generally all have no
casing information at all.
In total, this change:
* Does not change the size of libunicode.so (which is nice because,
generally, the 2-stage lookup tables are expected to trade a bit
of size for performance).
* Reduces the runtime of the new benchmark test case added here from
1.383s to 1.127s (about an 18.5% improvement).
Currently, the `isobmff` utility will only print the media file type
info from the FileTypeBox (major brand and compatible brands), as well
as the names and sizes of top-level boxes.
For malformed tables which only have cells with span greater than 1, the
content sizes for row and column aren't initialized to non-zero values.
Avoid undefined behavior in such cases, which sometimes show up on
Wikipedia.
This image is exactly the same as the previous one, excepted the RCT
transformation. It has been generated with:
Width 64
Height 64
RCT 29
Upsample 2
Bitdepth 10
if N > 300
- NE -6
- W 6
We currently produce a single table for all categories of code point
properties (GeneralCategory, Script, etc.). Each row contains a field
indicating the range of code points to which that property applies. At
runtime, we then do a binary search through that table to decide if a
code point has a property.
This changes our approach to generate a 2-stage lookup table for each of
those categories. There is an in-depth explanation of these tables above
the new `create_code_point_tables` method. The end effect is that code
point property lookup is reduced from a binary search to constant-time
array lookups.
In total, this change:
* Increases the size of libunicode.so from 2.7 MB to 2.9 MB.
* Reduces the runtime of the new benchmark test case added here from
3.576s to 1.020s (a 3.5x speedup).
* In a profile of resizing a TextEditor window with a 3MB file open,
the runtime of checking if a code point has a word break property
reduces from ~81% to ~56%.
We started generating this data in commit 0505e03, but it was unused.
It's still not used, so let's remove it, rather than bloating the size
of libunicode.so with unused data. If we need it in the future, it's
trivial to add back.
Note we *have* always used the block name data from that commit, and
that is still present here.
Auto margins used together with justify-content would previously
result in children being positioned outside their parent. This was
solved by letting auto margins take precedence when they are used,
which was already implemented to some extent before, but not
fully.
Containers with both flex reverse and justify content would
sometimes place children outside the container. This happened
because it assumed any reversed container would have items
aligned to the right, which isn't true when using eg. `flex-end`.
Both `justify-content: start` and `justify-content: end` are now
also independent of the reverseness.
After switching to fixed-point arithmetic in CSSPixels, it no longer
supports representing infinite values, which was previously the case
for remaining_free_space in FFC. Using Optional that is not empty only
when value is finite to store remaining_free_space ensures that
infinity is avoided in layout calculations.
This fixes an assertion on https://amazon.com/ since WindowProxy
would advertise "0" as an own property key, but then act like it was
a bogus property when actually queried for it directly.
Before this change, we always derived a box's baseline from its last
child, even if the last child didn't have any line boxes inside.
This caused baselines to slip further down vertically than expected.
There are more baseline alignment issues to fix, but this one was
responsible for a fair chunk of trouble. :^)
I misunderstood the spec step for checking whether the host 'ends with a
number'. We can't simply check for it if ends with a number, this check
is actually an algorithm which is required to avoid detecting hosts that
end with a number from an IPv4 host.
Implement this missing step, and add a test to cover this.
After the CSSPixels implementation evolved from a wrapper of double
to a fixed-point saturated math arithmetic implementation, it makes
sense to have separate tests for it.
Using fixed-point saturated arithmetics for CSSPixels allows to avoid
accumulating floating-point errors.
This implementation is not complete yet: currently saturated
arithmetics implemented only for addition. But it is enough to not
regress any of layout tests we have :)
See https://github.com/SerenityOS/serenity/issues/18566
Returning a reference resulted in Mail's use of Promise causing a crash.
Also, awaiting an already-awaited promise is an odd thing to do anyway,
so let's just make it release the resolved/rejected value instead of
returning a reference to it.
Co-Authored-By: Valtteri Koskivuori <vkoskiv@gmail.com>
Follow the computing column measures section of the specification, which
gives an algorithm for setting intrinsic percentage widths when spanning
columns are involved.
This is intended to be used in adding test-js tests where there is
different behaviour between the AST interpreter and bytecode mode.
In particular, this is useful for tests which fail in AST, but pass in
bytecode, as the AST interpreter is run in CI but bytecode is not.
This image uses the modular encoding with a very simple prediction tree.
It also makes use of two features: upsampling (x2 factor) and a
non-standard bit depth (10 bits). The file has been generated on
https://jxl-art.surma.technology/ , with the following input:
Width 64
Height 64
Upsample 2
Bitdepth 10
if N > 300
- NE -6
- W 6
Change how we store type of columns. It was used where the specification
only distinguishes between percent and everything else, so it makes more
sense to store and use it as a boolean.
The specification says we should distribute excess width proportionally
to the width of the cell, not to the preferred increment. Doing the
latter leads to distributing all excess width to just the cells which
demand some increment, even if it's very modest. Moreover, there's code
which partially implements the correct criteria just below the one we
remove here.
These passes have not been shown to actually optimize any JS, and tests
have become very flaky with optimizations enabled. Until some measurable
benefit is shown, remove the optimization passes to reduce overhead of
maintaining bytecode operations and to reduce CI churn. The framework
for optimizations will live on in git history, and can be restored once
proven useful.
The Heap::uproot_cell() API was used to implement markAsGarbage() which
was used in 3 tests to forcibly destroy a value, even if it had
references on the stack or elsewhere.
This patch rewrites the 3 tests that used this mechanism to be
structured in a way that allows garbage collection to collect the values
as intended without hacks. And now that the uprooting mechanism is no
longer needed, it's uprooted as well.
This fixes 3 test-js tests in bytecode mode. :^)
I added this file thinking it was necessary for the wpt run command.
However, it's only needed for updating expectations metadata. Since wpt
run always regenerates MANIFEST.json before updating expectations, we
can safely delete this file from the repository.
Reordering these calls allow us to ensure that all encoders are able to
return the size of the image before they are requested to decode the
whole bitmap.
The Test262RunnerHandler class in test-test262 was made in order to
spawn a subprocess, connect to its input/output error pipes, and obtain
its return value.
Later on, a copy of this implementation was added to TestSed with
modifications, such as adding support for reading from the output pipes
as well.
Unify these two implementations into a new Core::Command class. This new
implementation is more closely modeled from the TestSed implementation
due to the extra functionality it implemented.
Once we've resolved the used flex item width & height, we should allow
percentage flex item sizes to resolve against them instead of forcing
flex items to always treat percentages as auto while doing intrinsic
sizing layout.
Regressed in 8dd489da61.
When specifying either `background-position-x: right` or
`background-position-y: bottom` without an offset value no
EdgeStyleValue was created.
However, the spec says the offset should be optional.
Now, if you do not provide an offset, it creates the EdgeStyleValue
with a default offset of 0 pixels.
We do this by piggybacking on FormattingContext helpers instead of
reinventing the wheel in FlexFormattingContext.
This fixes an issue where `min-width: fit-content` (and other
layout-dependent values) were treated as 0 on flex items.
This makes the cookie banners look okay on https://microsoft.com/ :^)
This is just a straight (and fairly inefficient) implementation of IPv6
parsing and serialization from the URL spec.
Note that we don't use AK::IPv6Address here because the URL spec
requires a specific serialization behavior.
If an inline-block has a percentage height that relies on the auto
height of the containing block, it should always resolve to the
automatic height of the box, regardless of the percentage value. This
change may seem confusing, but it aligns with the behavior of other
engines.
Unlike all other primitives elliptical arcs are non-trivial to
manipulate, it's tricky to correctly apply a Gfx::AffineTransform to
them. Prior to this change, Path::copy_transformed() was still
incorrectly applying transforms such as flips and skews to arcs.
This patch very closely approximates arcs with cubic beziers (I can not
visually spot any differences), which can then be easily and correctly
transformed in all cases.
Most of the maths here was taken from:
https://mortoray.com/rendering-an-svg-elliptical-arc-as-bezier-curves/
(which came from https://www.joecridge.me/content/pdf/bezier-arcs.pdf,
now a dead link).
This tests that we can successfully parse the "everything" TVG files,
which make use of every feature in TinyVG.
Test files taken from https://github.com/TinyVG/examples (MIT).
This test proves the ability of TransformStream to execute
caller supplied code in the flush callback, and have access to
TransformStreamDefaultController.
This test proves the ability of TransformStream to execute
caller supplied code in the start callback, and have access to
TransformStreamDefaultController.
This test proves the ability of TransformStream to execute to execute
caller supplied code in the transform callback that can transform
incoming chunks, and have access to TransformStreamDefaultController.
There are two parts to this fix:
- First, StyleProperties::transformations() would previously omit calc()
values entirely when returning the list of transformations. This was
very confusing to StackingContext which then tried to index into the
list based on faulty assumptions. Fix this by emitting calc values.
- Second, StackingContext::get_transformation_matrix() now always calls
resolve() on length-percentages. This takes care of actually resolving
calc() values. If no reference value for percentages is provided, we
default to 0px.
This stops LibWeb from asserting on websites with calc() in transform
values, such as https://qt.io/ :^)
This change implements following paragraph from placement algorithm in
the spec:
"If the largest column span among all the items without a definite
column position is larger than the width of the implicit grid, add
columns to the end of the implicit grid to accommodate that column
span."
There were places in the grid implementation code with copies of this
text, but those were completely unrelated to the code where they were
being pasted so I removed them.
There were two problems:
1. parse_compressed_object_with_index() parses indirect objects
without going through Parser::parse_indirect_value(), so
push_reference() / pop_reference() weren't called.
Manually call them, both for the indirect object containing
the object stream and for the indirect object within the
object stream.
2. The indirect object within the object stream got decrypted
twice: Once when the object stream data itself got decrypted,
and then incorrectly a second time when the object data within
the stream was read. To fix, disable encryption while parsing
object stream data (since it's already decrypted).
The test is from http://opf-labs.org/format-corpus/pdfCabinetOfHorrors/
which according to readme.md at the same location is CC0.
I created this by typing "sup" into TextEdit.app on macOS 13.4,
hitting Cmd-P to bring up the print dialog, clicked the PDF button
at the bottom, changed Title and Author to "sup", clicked
"Security Options…", and checked "Require password to open document"
(with password "sup").
This file tests several things:
- It has a compressed stream as first object. This used to make the
linearization dict detection logic assert.
- It uses AES as encryption key using version 4 of the encryption
dict. This used to not be implemented.
Max width shouldn't be tied to min width, commit d33b99d went too far
and made them the same when the table-root had a specified percentage
width.
Fixes#19940.
Since the underlying HTML::Window can change, caching property accesses
on WindowProxy is not as simple as remembering the shape. Let's disable
caching here for now. We can come back to it in the future when we have
no low-hanging fruit left. :^)
Fixes an assertion failure on https://twinings.co.uk/
The previous iteration of this API was somewhat odd and rough in random
places, which degraded usability and made less than perfect sense.
This commit reworks the API to be a little closer to more
conventional promise APIs (a la javascript promises).
Also adds a test to ensure the class even works.
Make sure the insets and margins calculated according to the spec are
not later ignored and ad-hoc recomputed in
layout_absolutely_positioned_element.
Use the static position calculation in a couple of places where the
spec (and comment) was indicating it should be used.
Fixes#19362
The tests still pass, but opening the files in Ladybird and Safari or
Firefox shows clearly where the layouting in Ladybird is incorrect
for some absolute positioned elements. The previous 1px border was
subtly hiding some issues.
This now searches the memory in blocks, which should be slightly more
efficient. However, it doesn't make much difference (e.g. ~1% in LZMA
compression) in most real-world applications, as the non-hint function
is more expensive by orders of magnitude.
The "operation modes" of this function have very different focuses, and
trying to combine both in a way where we share the most amount of code
probably results in the worst performance.
Instead, split up the function into "existing distances" and "no
existing distances" so that we can optimize either case separately.
We will be adding extra logic to the CircularBuffer to optimize
searching, but this would negatively impact the performance of
CircularBuffer users that don't need that functionality.
When the containing block has an indefinite width, any descendants with
a percentage size should resolve that against 0, not infinity.
Fixes an assertion failure when loading https://www.gnu.org/
We achieve this by making properties that accept a custom-ident value
skip the "someone else's vendor prefix" check for values that start with
a `-` character.
This fixes an issue where e.g `font-family: Arial, -apple-system` would
be rejected by the parser completely. We now treat `-apple-system` like
an identifier in such cases.
Also add `valid-types` metadata for the `font-family` property so this
actually works. :^)
When sizing under a max-content constraint, we allow flex lines to have
an infinite amount of "remaining space", but we shouldn't let infinity
leak into the geometry of items. So treat it as zero in arithmetic.
This fixes an issue where inline SVGs with natural aspect ratio (from
viewBox) but no natural width or height could get an infinite size as
flex items.
All of the following properties in the font shorthand can be `normal`:
- font-style
- font-variant
- font-weight
- font-stretch
This means that we must allow up to four consecutive `normal` at the
start of a font shorthand value.
This fixes an issue where a BOM at the head of a style sheet would be
passed verbatim to the parser, who would then interpret it as an ident
token and (after some confusion) fail to parse the first rule, but then
carry on with the rest of the sheet.
Anonymous wrapper boxes inherit style from their layout tree parent,
and since style data is per-layout-node, we have to manually sync them
from parent to anonymous children when something changes.
This is not very elegant or efficient, so I've left a FIXME about
solving it in a nicer way.
This fixes horizontal dog alignment on https://waffles.dog/ :^)
As it turns out, Layout::TreeBuilder never managed to wrap text within
table boxes in anonymous wrapper boxes, since it relied on checking
text_for_rendering(), and that was never initialized during that early
stage of tree building.
This patch fixes the issue by making text_for_rendering() compute the
(potentially collapsed) text lazily when called.
Note that the test included with this patch is still totally wrong,
but that is now a TFC problem rather than a TreeBuilder problem. :^)
There were multiple bugs in the parsing algorithm for handling text
occurring inside a `table` element:
- When there was pending non-whitespace text inside a table, we only
flushed one token instead of all pending tokens.
- Also, we didn't even flush one of the right tokens, but instead the
token that caused the flush to happen.
- Once we started flushing the right tokens, it turned out we had not
yet implemented character insertion points expressed as "before X".
- Finally, we were not exiting the "in table text" mode after flushing
pending tokens, effectively getting us stuck in that mode until EOF.
Assertion fails if the point is outside of the rect. This was introduced
in introduced in #18970 and causes serenity to crash when changing to 2x
resolution for a monitor, if the cursor after resizing is outside of
the new screen.
Added test to reproduce.
Computing the table width algorithm bifurcates based on whether
table-root width is auto. We only adjust the used table width based on
cell percentage widths on the auto branch, thus the same check is needed
when we initialize cell widths.
Cell percentage widths are relative to table width, not containing
block width. If the table width is auto, there isn't a normative
specification, only a brief mention that the user agent should try to
meet it.
As a starting point, we increase the width of the table such that it's
sufficient to cover min-width of cells with a percentage width. This
matches the behavior of other browsers, at least for simple cases.
This removes a lot of duplicated stream creation code from the plugins,
and also simplifies the way that the appropriate plugin is found. This
mirrors the ImageDecoderPlugin design and necessitates new sniffing
methods on the loaders.
This ensures that min-content contributions from cells with no content
are computed using their calculated values, which are never considered
for min-content before then. The specification diverges from column
measures algorithm, which doesn't use specified width of cells anywhere.
The CSS box-shadow property takes 2-4 properties that are `<length>`s,
those being:
- offset-x
- offset-y
- blur-radius
- spread-radius
Previously these were resolved directly to concrete Lengths at parse
time, but now they will be parsed as LengthStyleValues and/or
CalculatedStyleValues and be stored that way until styles are later
resolved.
The used width is already a content width, which doesn't include
borders. Border widths should be subtracted from the specified width
instead, since that initially specifies the total width including
borders, for consistent comparison. Also handle table box padding as an
additional fix.
There are hundreds of test262 tests with the following metadata line:
flags: []
Other engine runners are apparently able to ignore those lines, so we
should as well.
On style update, we have to preserve the invariant established when we
built the layout tree - some properties are applied to the table wrapper
and the table box values are reset to their initial values.
This also ensures that the containing block of a table box is always a
table wrapper, which isn't the case if we set absolute position on the
box instead of the wrapper.
Fixes#19452.
The JS::VM now owns the one Bytecode::Interpreter. We no longer have
multiple bytecode interpreters, and there is no concept of a "current"
bytecode interpreter.
If you ask for VM::bytecode_interpreter_if_exists(), it will return null
if we're not running the program in "bytecode enabled" mode.
If you ask for VM::bytecode_interpreter(), it will return a bytecode
interpreter in all modes. This is used for situations where even the AST
interpreter switches to bytecode mode (generators, etc.)
This was meant to be a temporary unit testuntil we could run test-js
in bytecode mode. This has been possible for a long time now, so let's
remove the unnecessary extra program.
This fixes the issue when size of abspos items is considered to be
resolvable without performing layout which is not correct in the
scenarious when top/right/bottom/left properties are not auto.
Return error when input svg is not valid and SVGSVGElement is not
present in the tree instead of doing svg_root nullptr dereference.
Fixes crash on https://apps.kde.org/en-gb/
Adding undistributable space right before setting the content width is
incorrect when it's a percentage. Follow the specification and add it to
GRIDMIN and GRIDMAX instead.
In particular, in BFC:
- Non-floating, non-replaced elements
- Floating, non-replaced elements
- Floating, replaced elements
The first two regressed in 1d76126abe
The third one seems to have been introduced by this regression, as it
was seemingly copied from compute_width_for_floating_box in
7f9ede07bc
The fix here has two parts:
1. Don't use the fallback viewBox at all if we're not in SVG-as-image.
2. Don't make a fallback viewBox with zero width and/or height.
This fixes a crash on Bandcamp pages. Thanks Tim Flynn for reporting!
The shortcut we put in place didn't resolve percentage widths and
ignored border spacing. We can still return early after we compute the
width per the specifications.
While CSS 2.2 does tell us to use the "auto height for BFC roots"
calculation when resolving auto heights for abspos elements, that
doesn't make sense for other formatting context roots, e.g flex.
In lieu of implementing the entire new absolute positioning model from
CSS-POSITION-3, this patch borrows one small nugget from it: using
fit-content height as the auto height for non-BFC-root abspos elements.
This just works at the moment after e19892a099, but if we ever do
the FIXME in ColorIndexingTransform::transform(), this test will
remind us to think of this case there too.
catdog-alert-13-alpha-used-false.webp is identical to
catdog-alert-13.web but with the byte at offset 0x2a changed from
0x10 to 0x00 -- that is, the bit in the VP8L header that stores
`is_alpha_used` is cleared.
See the commit message of e19892a099 for more information.
When embedding an SVG in an img element, if the external SVG's root
element has both width and height attributes, but no viewBox attribute,
we now create a fallback viewBox with "0 0 width height".
This appears to match the behavior of other browsers. Inspired by
discussion on Mozilla's bug tracker:
https://bugzilla.mozilla.org/show_bug.cgi?id=614649
If we don't paint, SVG-as-image documents don't get laid out, and so
have 0x0 size throughout.
This change is also generally nice, as it makes the painting code run
on all the layout tests, increasing coverage. :^)
Compute the contributions to a spanning cell width from each cell in the
span. This better handles uneven column widths, since each cell
contribution is proportional with its own width as opposed to the own
width of the first cell in the span.
This better matches the behavior of other browsers and further aligns
with the specification.
The part in FFC where we ask the parent formatting context to size the
flex container midway through layout is really weird, but let's at least
be consistently weird for BFC and IFC. Since IFC always works within its
parent BFC, it can simply forward these requests to the BFC.
This fixes an issue where inline-flex containers incorrectly had main
axis margins subtracted from their content size.
Two files are used both as test inputs for the webp decoder test and
for the icc profile test.
Use redundant copies of these two files for the two usecases, since
different parts of the files are used in both tests (and we could
remove the unneeded parts later).
With multi-line text cells, we don't reliably know the height would stay
the same as the one set by the independent format context run. In such
situations, we can end up with a table box which is sized inconsistently
with the grid boxes of the table due to differences in line breaks.
simple-vp8l-alpha-used-false.webp is a copy of simple-vp8l.webp,
with the byte at offset 0x18 changed from 0x10 to 0x00 -- that
is, the bit in the VP8L header that stores `is_alpha_used` is cleared.
We would already allocated a BGRx8888 instead of a BGRA8888 bitmap,
but keep actual alpha data in the `x` channel.
That lead to at least `image` still writing a PNG with an alpha channel.
So explicitly set the alpha channel to 0xff when is_alpha_used is false,
to make sure all consumers of decoded lossless webp data have behavior
consistent with other webp readers.
In practice, webp encoders usually don't write files that have
`is_alpha_used` set to false and then write actual alpha data to their
output. So this is rarely observable. However, for example for
lossy+ALPH webp files, the lossless webp used to store the ALPH channel
has `is_alpha_used` set to false and all channels but green are 0
(since the lossless green channel stores the alpha channel of a
lossy+ALPH webp). So if we dump such a bitmap to a standalone webp
file (e.g. with the temporary debugging code in fc3249a1ca),
then without this commit here, `image` would convert that webp to
a fully transparent webp, while other webp software would correctly
display the green image with opaque alpha.
I was debugging a different issue in Ladybird, and noticed that
completing relative file URLs with URL::complete_url didn't seem to work
right. This test case covers both the working https case, as well as the
file URL case fixed by the previous commit.
In compute_table_box_width_inside_table_wrapper, we should only consider
available_width when it's valid. Values which come from {min,
max}-content constraints aren't meaningful and shouldn't be considered
for the cap.
Absolutely positioned elements should have their percentage sizes
resolved against the padding box of the containing block, not the
content box.
From CSS-POSITION-3 <https://www.w3.org/TR/css-position-3/#def-cb>
"..the containing block is formed by the padding edge of the ancestor.."
When resolving a percentage min-width or min-height size against a
containing block currently under a min-content constraint, we should act
as if the containing block has zero size in that axis.
"display: max-content" is not a thing. The test was actually not working
correctly, it just looked like it did. Now it has correct metrics for
the body element.
Don't try to implement this AO in bytecode. Instead, the bytecode
Interpreter class now has a run() API with the same inputs as the AST
interpreter. It sets up the necessary environments etc, including
invoking the GlobalDeclarationInstantiation AO.