Per css-sizing-3:
Additionally, the size of the containing block of an absolutely
positioned element is always definite with respect to that element.
As I understand this, it doesn't mean that all absolutely positioned
boxes have definite size, but that the containing block of an absolutely
positioned descendant has definite size from the perspective of the
descendant.
Since style update is driven by Document, moving a node with dirty style
from one document to another means that we have to schedule a style
update in the new document.
If we had a scheduled update of either of these kind, make sure to
cancel it after performing an update. Otherwise we might do a redundant
second update with the same results.
This could happen if something schedules an async layout, and before it
can happen, something requires a sync layout, which we do right away.
This paves the way for the rejectionhandled and unhandledrejection
events.
It's also used by core-js (in browsers, at least) to check whether
Promise needs to be polyfilled, so adding it should allow more websites
to leverage LibJS's native Promise implementation :^)
When computing whether whitespace should be collapsed or not, we have to
consider empty fragments, since <br> will produce an empty fragment to
force a line break.
LineBox::is_empty_or_ends_in_whitespace() is amended to look at the
length of the last fragment, and return true if it is 0.
A types which have special functions declared with "= default can be
trivially copied. Besides being good practice, the compiler might be
able generate copy and initialize code in a more optimized way.
Found By PVS-Studio: https://pvs-studio.com/en/docs/warnings/v832/
We can reduce the amount of padding the compiler adds in order to
ensure data alignment of member variables by ordering the types in
a struct by size in decending order.
Found By PVS-Studio: https://pvs-studio.com/en/docs/warnings/v802/
We now evaluate the conditions of `@media` rules at the same point in
the HTML event loop as evaluation of `MediaQueryList`s. This is not
strictly to spec, but since the spec doesn't actually say when to do
this, it seems to make the most sense. In any case, it works! :^)
The main thing missing is that we don't serialize the supports clause,
but for actually using a `@supports (something: cool) {}` rule in CSS,
it works!
The logic is handled by `CSSGroupingRule` and `CSSConditionRule`, so
`CSSMediaRule` only has to report if its condition matches.
Right now, that condition is always false because we do not evaluate the
media query.
Websites being able to query whether we support a given CSS feature
should prevent them from loading unnecessary polyfills for things we
already support! Or at least, that's the nice theory. :^)
... according to
https://www.w3.org/TR/css-conditional-3/#typedef-supports-condition
This works very similarly to `@media`, but is different enough to
require its own parsing. (Though, the draft of Conditional-4 currently
mentions combining the two into a `@when` rule.)
Made some small changes to parsing code to make this work. Notably,
making `consume_a_declaration()` fail gracefully instead of
`VERIFY()`ing.
The name is a little awkward, but this corresponds to the condition of a
`@supports` rule or the `CSS.supports("")` function.
A supports query only gets evaluated once, since its condition cannot
change during runtime. (We either support something or we don't, and the
spec specifically mentions that user preferences that disable features
do not affect the result here.) We keep a representation of it around
though, so that it can be serialized if needed. This is a little awkward
since we hold onto a `StyleDeclarationRule` which should be an internal
Parser class. This means making some Parser functions more public.
Potentially we could evaluate the Supports inside the Parser, and have
it only store a String representation of itself. But this works for now.
:^)
This is the `CSS` namespace defined in IDL here:
https://www.w3.org/TR/cssom-1/#namespacedef-css , not to be confused
with our `Web::CSS` namespace. Words are hard.
`CSS.escape()` lets you escape identifiers that can then be used to
create a CSS string.
I've also stubbed out the `CSS.supports()` function.
The recursive style update function was written a bit strangely and
would only mark descendants of the style update root as not needing a
style update.
With this patch, all nodes in the subtree now have clean style after a
style update finishes.
Layout depends on style (and not the other way around), so if the
document has dirty style when we enter update_layout(), make sure we
call update_style() before proceeding with the layout work.
This has the pleasant effect of coalescing some redundant layouts.
'static' for a function means that the symbol shall not be made public
for the result of the current compilation unit. This does not make sense
in a header, especially not if it's a large function that is used in
more than one place and not that performance-sensitive.
Previously: Length (and all nearly all of its inline method
definitions) depended on the definition of class CalculatedStyleValue.
Meanwhile, CalculatedStyleValue (and nearly all of its namespaced
structs) depended on the definition of class Length.
Thus, a compilation unit that (for example) only contains
#include <Userland/Libraries/LibWeb/CSS/Length.h>
would fail to compile.
This patch resolves this issue by pushing the inline definition of
various Web::CSS::Length methods into a different file.
Previously: CSSImportRule::loaded_style_sheet() (and others) depend on
the definition of class CSSStyleSheet. Meanwhile,
CSSStyleSheet::template for_each_effective_style_rule (and others)
depend on the definition of class CSSImportRule.
This hasn't caused any problems so far because CSSStyleSheet.h happened
to be always included after CSSImportRule.h (in part due to alphabetical
ordering).
However, a compilation unit that (for example) only contains
#include <Userland/Libraries/LibWeb/CSSImportRule.h>
would fail to compile.
This patch resolves this issue by pushing the inline definition of
Web::CSS::CSSStyleSheet::for_each_effective_style_rule and
for_first_not_loaded_import_rule into a different file, and adding the
missing headers.
Per the spec, only a BlockContainer" can have line boxes, so let's not
clutter up every Layout::Box with line boxes.
This also allows us to establish an invariant that BFC and IFC always
operate on a Layout::BlockContainer.
Note that if BlockContainer has all block-level children, its line boxes
are not used for anything. They are only used in the all inline-level
children scenario.
List item markers will never have children, so let's mark them as such,
which now allows our layout system to skip over their "insides" and
going straight to positioning instead.
Some boxes cannot have children (most commonly replaced elements),
and so there is nothing meaningful inside them to layout.
We now use the can_have_children() flag to quickly skip over such boxes
instead of creating a formatting context and other pointless busywork.