Constructed stylesheets updated their rule lists, but adopted documents
and shadow roots were not restyled when replace(), replaceSync(),
or disabled-state changes modified the sheet. That left several CSSOM
tests passing stale computed styles.
Invalidate stylesheet owners after those updates so adopted sheets
recompute promptly. Also set replace()-produced rules' parent
stylesheet so non-import rules keep their stylesheet context.
The imported baseURL test assumes a tuple origin, so move it to the
HTTP fixture now that replaceSync() actually triggers a restyle.
Scrollable overflow still assumed a top-left scroll origin and only
added trailing padding on the physical bottom edge. That broke
scrollWidth and scrollHeight for flex containers whose main or cross
axis was reversed by writing-mode, direction, flex-direction, or
wrap-reverse.
Teach flex layout to place wrapped lines using the computed cross-axis
direction and to measure scrollable overflow from the container's
actual scroll origin so reachable reversed overflow is preserved, the
unreachable side is clipped, and end padding is added on the correct
physical edge.
Keep per-item cross-axis placement using the existing behavior.
Applying full cross-axis reversal there regressed baseline alignment
tests, and zero-sized boxes exactly at the scroll origin must still
contribute descendant overflow, so the unreachable-overflow checks
need strict comparisons.
This makes negative-overflow-002 and negative-overflow-003 pass and
improves negative-overflow, align-content-wrap-003, and
overflow-with-padding.
Inline formatting contexts in vertical writing modes were measuring
intrinsic width from the line box width. That width still tracks the
line-height-sized horizontal span, so shrink-to-fit abspos sizing could
stay at 50px even when the text fragments only covered 25px.
Measure the physical horizontal extent from the line box fragments
instead, including the float-aware block formatting context path. This
makes orthogonal inline content report the correct intrinsic width.
Use the absolutely positioned box's own grid placement to resolve the
grid-area containing block rectangle instead of inheriting the nearest
in-flow grid item's area.
Keep the grid-specific static-position handling for axes with both
insets auto, but resolve mixed auto and explicit grid placement axes
against the augmented grid for direct children as well as descendants
inside grid items.
This fixes the imported abspos and alignment WPTs for values like
grid-row: 1 and grid-column: auto / 1 while keeping the reduced
descendant regressions passing.
Percentage row tracks in auto-height grids only participated in our
intrinsic sizing pass. We computed the grid container's intrinsic
height from that pass, but never reran row track sizing with the
now-known height, so percentage rows stayed content-sized and the
imported WPTs had recorded failures.
Reset the mutable track sizing state before rerunning the row pass,
rebuild row gap tracks against the resolved container height, and keep
the automatic content height from the intrinsic pass so parent layout
still resolves auto height correctly. Rebaseline the percentage-row
imports and the grid track parsing import that now improve with the
corrected percentage resolution.
The static-position rectangle for absolutely positioned flex children
still mapped cross-axis flex-start and flex-end directly to physical
start and end. That broke cases where the flex cross axis is reversed
by writing mode, direction, or wrap-reverse.
Teach the flex formatting context to derive the cross-axis direction
from its logical axes and wrap mode, and use that when resolving
cross-axis alignment for abspos static positioning. This clears the
newly imported position-absolute-013 test and improves a broader set
of existing flex abspos WPT baselines.
Import the css-flexbox abspos position-absolute-013 test from WPT so we
can track its current behavior locally.
The imported baseline currently has 432 subtests total, with 228
passing and 204 still failing.
Handle flex main and cross axes in logical terms so percentage
height resolution keeps working in vertical writing modes and
other orthogonal cases. Also let resolvable percentage max
cross sizes clamp stretched flex items.
The same change improves a broader set of imported css-flexbox
tests than the original percentage-heights cases. Update the
affected expectations in the same change so the resulting
behavior stays documented and the suite remains green.
When an absolutely positioned non-BFC element (flex, grid, etc.) has
auto height, we pre-compute its height from content before running
inside layout. Previously, this content-derived height was marked as
"definite", which incorrectly allowed descendants to resolve percentage
heights against it. Per CSS 2.1 section 10.5, percentage heights should
only resolve when the containing block's height is specified explicitly.
The fix is to simply not set has_definite_height when the CSS height is
auto. This naturally prevents percentage resolution through all existing
paths (set_node, should_treat_height_as_auto, calculate_inner_height)
without needing any new flags or per-site checks.
Two additional fixes enable this:
- In flex line cross-size clamping, remove the contains_percentage()
guard that prevented percentage min/max-height from resolving. These
percentages resolve correctly via calculate_inner_height's containing
block lookup, since the abspos element's containing block always has
a definite height.
- In grid item alignment, check should_treat_height/width_as_auto for
percentage preferred sizes, so they're treated as auto when the grid
container's height is indefinite (CSS Grid section 6.6).
Import flex percentage-heights-004 through -010 and -014 (ref tests),
and grid-percentage-rows-indefinite-height-001 and -002 (testharness).
The flex tests all pass. The grid indefinite-height tests have many
failures (16/120 pass and 0/4 pass respectively), reflecting known
gaps in our grid percentage row handling.
We now ignore all animation properties from `css-animations-1` declared
within keyframes, except `animation-timing-function`, which is treated
specially.
Allow CSS pseudo-element chaining with ::part() so that
selectors like ::part(title)::before can style pseudo-elements
within shadow DOM parts.
Parser changes (SelectorParsing.cpp): The pseudo-element
validation logic now tracks which pseudo-element appears first
and second in a compound selector. When multiple pseudo-elements
are found, the parser permits the selector only if the first is
::part() and the second is NOT ::part(). A maximum of two
pseudo-elements is enforced.
Selector changes (Selector.cpp, Selector.h): The Selector
constructor now stores the last pseudo-element (the styling
target) rather than the first. For ::part(foo)::before, the
selector reports ::before as its target. A new
m_contains_part_pseudo_element flag separately tracks whether
::part() is present for the selector engine.
Fixes 9 WPT tests: 6 in css/selectors/parsing/parse-part.html
for chained selector parsing, and 3 in
css/css-shadow-parts/multiple-scopes.html for correct scoping
of exported, middle-scope, and non-exported part selectors.
Implement the forwarded part names step of the CSS Shadow Parts
spec in ShadowRoot::calculate_part_element_map(). When a shadow
host has an exportparts attribute, the inner shadow root's part
element map is consulted and matching parts are added to the
outer shadow root's map under the exported name.
This supports both shorthand same-name forwarding (exportparts=
"foo") and renamed forwarding (exportparts="foo: bar"), and
chains transitively through nested shadow boundaries via
recursive part_element_map() calls.
Fixes 4 WPT tests: simple-forward, simple-forward-shorthand,
double-forward, and precedence-part-vs-part.
The main limitation here are that none of the container-query features
are parsed in a meaningful way; they all become `<general-enclosed>`.
Parsing for them will be added as they are implemented.
Import ref and text tests from css/CSS2/floats,
css/CSS2/floats-clear, css/CSS2/margin-padding-clear, and
css/CSS2/visuren.
These cover float placement, clear behavior, clearance calculations,
and margin collapsing with floats.
Add `ECMAScriptRegex`, LibRegex's C++ facade for ECMAScript regexes.
The facade owns compilation, execution, captures, named groups, and
error translation for the Rust backend, which lets callers stop
depending on the legacy parser and matcher types directly. Use it in the
remaining non-LibJS callers: URLPattern, HTML input pattern handling,
and the places in LibHTTP that only needed token validation.
Where a full regex engine was unnecessary, replace those call sites with
direct character checks. Also update focused LibURL, LibHTTP, and WPT
coverage for the migrated callers and corrected surrogate handling.
The definition of syntax in the "css-properties-values-api" spec (which
is used for the `@property/syntax` descriptor) is slightly different
from the definition of `<syntax>` in the "css-values" spec (which we
implement) in that it limits literal idents to exclusively
`<custom-ident>`s (i.e. not CSS-wide keywords or "default").
`<custom-ident>`s are also case-sensitive so that behavior is
implemented for syntax matching here as well
Previously we would consider an alternative syntax child to be a match
as long as parsing produced a value, even if there were trailing tokens
(which would later invalidate it within `parse_with_a_syntax`). This
meant that we wouldn't consider later alternatives which may actually
produce a valid match.
Per the CSS Transforms spec, when interpolating rotate3d() functions
with equal normalized direction vectors (or when one angle is zero),
the rotation angle should be interpolated numerically rather than
using quaternion slerp.
Previously we always used quaternion slerp, which cannot represent
rotations beyond 360 degrees. This meant that animating from
rotateY(0deg) to rotateY(3600deg) produced no visual animation, since
both quaternions are identical (3600 mod 360 = 0).
Now we detect when axes match and interpolate the angle directly,
correctly preserving multi-turn rotations. This fixes 168 WPT tests.
The :host::part() pattern allows a shadow DOM's own stylesheet to
style its internal elements that have been exposed via the part
attribute. Previously, ::part() rules were only collected from
ancestor shadow roots (for external part styling), but never from the
element's own containing shadow root.
Fix this by also collecting ::part() rules from the element's own
shadow root in collect_matching_rules(). Additionally, fix the
selector engine's ::part() compound matching to preserve the
shadow_host when the rule originates from the part element's own
shadow root, allowing :host to match correctly in the same compound
selector.
This fixes 2 previously failing WPT tests:
- css/css-shadow-parts/host-part-002.html
- css/css-shadow-parts/host-part-nesting.html
Previously, during grid track maximization we used the total number of
grid tracks as the denominator when distributing the available free
space. Using a larger denominator than expected meant that the
algorithm needed a larger number of iterations than necessary to
converge leading to rounding errors in the final track sizes.
The :nth-child(), :nth-last-child(), :nth-of-type(), and
:nth-last-of-type() pseudo-classes previously returned false for
elements that have no parent node. This meant that calling
element.matches(":nth-child(1)") on a standalone element created
via document.createElement() would incorrectly return false.
An element without a parent has no siblings, so its index is 1. The
simpler child-indexed pseudo-classes (:first-child, :last-child, etc.)
already handled this case correctly by checking for sibling presence
without requiring a parent. This change brings the nth-* variants in
line with that behavior by guarding the sibling iteration loops on
parent existence rather than returning false early.