Seed the page background fallback from the platform color scheme before
WebContent has painted. Update the same fallback when the platform theme
changes, and when the preferred color scheme is forced through the debug
menu, so unpainted web view areas use the matching Canvas color.
Display lists owned the accumulated visual context tree through a
ref-counted pointer. That tied visual-context state to display-list
lifetime and made compositor updates treat the two as one unit, even
though AVC trees need to become independently updateable compositor
state.
Make accumulated visual context trees plain versioned values, have each
display list store the compatible tree version, and pass the matching
tree alongside display-list updates and replay calls. Replay verifies
that the provided tree matches the display list before executing it.
This prepares the compositor for receiving AVC tree updates separately
from display-list updates: it now accepts the tree as a separate update
parameter, stores it next to the display list, and uses that stored tree
for replay and async-scroll hit testing. Nested display-list resources
carry their own tree snapshots for the same version check.
Store grid container layout data on the grid container's paintable box
during layout.
The data includes computed track, line, and named-area geometry for
Firefox DevTools protocol serialization. It also carries the resolved
grid-template-columns and grid-template-rows values used by
getComputedStyle(), so PaintableBox does not need separate grid
template storage.
Resolve prelude-less @scope roots from the owning stylesheet context
during matching. This lets implicit scoped declarations target a style
element's parent. It also lets implicit shadow-root scopes use the
shadow host as the scoping root.
Use :where(:scope) for nested declarations directly inside `@scope`.
The concrete scoping root is supplied by `@scope` resolution during
selector matching, so CSSNestedDeclarations does not need to encode the
scope-start selector itself.
DisplayListPlayer::execute() used to flush the active painting surface
as part of replay. That made replay and submission inseparable, so
callers could not add extra painting after replay without either
accepting a stale submission boundary or flushing again.
Expose flush(PaintingSurface&) on the player and make execute() only
replay commands. Existing callers now issue an explicit flush at the
same point where the implicit flush used to happen, keeping behavior
unchanged while making the submission boundary visible to compositor
code.
Avoid rewriting CSSOM custom properties when the parsed value and
priority match the existing declaration. This mirrors the longhand
setProperty path and prevents repeated identical root custom property
writes from invalidating inherited style across the whole document.
Extend the style invalidation counter test to cover identical and
changed custom property assignments.
Use StyleValue's computational-independence predicate when deciding
which specified values to retain for inherited-style recomputation.
Compound values such as shadows, filters, lists, and calc trees now
reuse their existing dependency tracking instead of the old bare-length
check.
Treat missing tuple entries and keyword-only edge offsets as
computationally independent. These nullable slots are part of the
parsed value representation, and the inherited dependency tracking now
uses the shared computational-independence query for specified values.
Add viewport resize coverage for media query changes that update root
font metrics while a descendant uses font-relative lengths inside
box-shadow and filter values.
When @media rules change match state, avoid treating that as a
whole-document stylesheet change. Record the rules under the query
that became effective or ineffective, build the normal stylesheet
invalidation set from those rules, and invalidate only matching
elements. Keep broad invalidation for rule kinds whose effects are not
selector-targetable.
Preserve cascade-wide fallout by reusing stylesheet-change shadow
effect analysis for broad invalidations inside shadow roots. This keeps
:host and slotted content current when active rules in the same shadow
scope can match there.
Also report an imported stylesheet's owner rule when the imported
sheet's own media gate changes. Layered @import rules can affect layer
ordering even when the imported sheet contributes no rules, so they
need the same broad invalidation treatment as other cascade-wide rules.
Add viewport resize coverage for media query breakpoints, broad
shadow-root media invalidation, and empty layered imports whose media
gate changes layer order.
Parse subgrid track listings for grid-template rows and columns,
including fixed and auto-fill name-repeat line-name lists. Preserve
the subgrid keyword through computed values and shorthand serialization,
and make interpolation discrete instead of routing subgrid lists through
the explicit track interpolation path.
Import WPT coverage for subgrid grid-template parsing and computed
values, and add text coverage for discrete subgrid track-list animation.
Record when computed properties depend on viewport metrics while
resolving lengths. Carry that information through font metrics so
font-relative lengths can be associated with viewport-sized fonts.
This keeps the dependency tracking local to style computation and gives
later viewport resize invalidation a way to find affected elements.
ImageStyleValue stored GC-managed request, stylesheet, and animation
timer references as strong GC::Ptr fields even though image style values
are refcounted objects. When such a style value outlives the GC object
that normally visits it, those fields can keep stale pointers after GC
collects the referents. On Steam this allowed a stale image resource
request to be read as unrelated image data, making carousel SVG arrows
render at the wrong size.
Store these back references as GC::Weak instead. Reachable style values
still use live requests, stylesheets, and timers normally, but detached
values observe null after the GC collects the referent and can reload or
skip the now-dead association instead of dereferencing reused GC memory.
Keep a local timer handle while installing the timeout callback so setup
does not rely on the weak member.
With the image style values no longer hiding strong GC edges, remove the
obsolete IGNORE_GC annotation from CSSStyleSheet's pending image list.
Compound selectors with a non-rightmost pseudo-class used to register
their descendant and sibling invalidation plans directly under the
pseudo-class property. A selector like `.item:hover * .target` ran
the descendant plan for every hovered element, even when that element
could not match `.item`.
Store those non-rightmost plans behind a guard made from stable class
and id subject features in the same compound selector. Deliberately
leave pseudo-classes out of guards, since one mutation can change
multiple state pseudo-classes at once. Also leave tag and attribute
selectors out, since their matching depends on document and namespace
case-sensitivity that the guard property does not carry.
The new style-invalidation test covers the GitHub-shaped
`:hover * :not(...)` case, co-invalidated `:link` and `:any-link`,
partial or complex `:is()`/`:where()` alternatives, and case-sensitive
SVG tag and attribute selectors.
Replace PseudoClassInvalidator's subtree scan with targeted
invalidation for elements whose pseudo-class state changes. This scopes
state changes to affected selectors instead of rechecking a whole
common-ancestor subtree.
Use the ancestor chain that matches each pseudo-class. Hover walks the
shadow-including chain. :focus-within walks the flat-tree chain, so
slotted content invalidates its assigned slot and relevant shadow-tree
descendants. Focus, FocusVisible, and Target invalidate just the state
node.
Route each affected element through Element::invalidate_style with the
pseudo-class property. This uses the same invalidation-plan machinery as
Disabled, Checked, and other pseudo-class state changes.
Interaction state pseudo classes are not tracked in :has() metadata, so
schedule :has() ancestor invalidation explicitly when the state flips.
The callers no longer need cross-scope branching. The chain walk handles
shadow boundaries, and property invalidation already visits every
observer style scope.
Do not invalidate shadow-root rule caches when the document user style
sheet changes. Shadow trees still need style invalidation because
document user rules can match their descendants, but their local author
rule caches do not include the document user sheet.
Since user and content-blocker sheets now live only in the document
scope, shadow-DOM state changes also have to consult the document user
selector insights for :has() and pseudo-class invalidation.
Add content blocker coverage for user-style refreshes, shadow :has()
state changes, and shadow pseudo-class invalidation.
Cache lightweight selector insights on each stylesheet so cold style
scopes can answer whether :has() invalidation is relevant without
building a complete rule cache. This avoids forcing rule caches for
shadow roots whose active sheets do not contain :has() selectors.
Imported sheets contribute to their parent sheet's effective rules, so
an imported sheet load or CSSOM change also clears ancestor selector
insight caches.
Add test-only counters and regression coverage for cold shadow roots
with and without :has() selectors, plus delayed imported :has() rules.
Do not process pending :has() mutation invalidation for shadow roots
that have no active style sheets. Such scopes cannot contain shadow
rules with :has(), and document-level user rules are handled by the
document style scope before shadow roots are visited.
Add a text test that mutates an unstyled shadow root while document
:has() invalidation is active, covering the safety boundary for this
shortcut.
Content blocker cosmetic rules now live in the document style scope, so
single constructed stylesheet shadow roots can still reuse their shared
style cache when cosmetic rules are enabled. This keeps the existing
sharing fast path active on pages with many constructed shadow roots.
Build the user stylesheet only for document style scopes, since user
rules are already considered relevant across shadow boundaries during
rule matching. This avoids regenerating and reparsing the same cosmetic
content blocker stylesheet for every shadow root in the document.
Keep the generated cosmetic stylesheet cached on the Document and clear
it whenever user style is invalidated, so content blocker changes still
produce fresh CSS for the next style update.
The base URL change handler checked whether any style scope contained
a `:local-link` rule before walking the document's links, this forced
a rule cache rebuild, which is generally slower than the link walk we
were trying to avoid.
On Speedometer2 the duplicated rule-cache and invalidation-set
construction accounted for roughly 4% of total samples. Removing the
gate lets the URL-unchanged early-exit handle the no-op case and runs
the link walk only when the URL actually changes, which the profile
showed to be inexpensive on its own.
Represent WebIDL C++ types with a single CppType model that tracks
nullability, optional presence, and contained storage.
GC-like values now use GC::Ref/GC::Ptr directly, while containers choose
"plain", "Root", or "Conservative" container types depending on what
they contain. For example, sequence<Element> becomes a RootVector of
GC::Ref values, while sequence<SomeDictionary> becomes a
ConservativeVector only when the dictionary contains GC-like values.
This moves the generated bindings away from wrapping GC values in
GC::Root by default.
This has broad fallout as the types passed to interfaces for GC
objects changes almost fully across the board.
This change matches the style used in the previous commits. No
regression tests have been added because this change is not observable,
as `FontStyleStyleValue` currently ignores the oblique angle.
Previously, a font width/stretch descriptor with a calc() expression
containing font-relative units cause a crash when read because
`set_stretch_impl()` expects values to be absolutized. This change
moves absolutization into `set_stretch_impl()`, sourcing the length
resolution context from the connected stylesheet's owning document.
Keep animated ImageStyleValue frame advancement owned by the
style value. The current frame and loop state live there, so a
separate document scheduler would duplicate ownership of that state.
Start the ImageStyleValue timer only while it has layout clients.
Stop it when the last client unregisters, or when a finite animation
completes. Expose a document-scoped active timer count through
internals for focused regression tests.
Clear image observers when layout nodes detach. Use current-node
cleanup for per-DOM-node clearing, and explicit subtree cleanup for
tree replacement, full tree teardown, and synthetic pseudo-elements.
This keeps large document clearing linear.
Unregister generated-content image providers during layout detach
instead of waiting for GC to finalize the provider.
Cover hidden animated background images, generated content images,
layout node replacement, full layout tree teardown, and document
scoping for the internals counter.
Use an empty namespace table when parsing a nested rule through a
grouping rule that no longer has a parent stylesheet, and skip owner
invalidation in that detached case.
Add a crash test covering selectorText mutation and nested insertRule
after a top-level style rule has been deleted from its constructable
stylesheet.
Fall back to discrete transform interpolation when a remaining
transform list needs a reference box to become a matrix and none is
available. Percentage translate values otherwise reached
Length::from_style_value() without a percentage basis.
Add a crash test covering computed Typed OM access to an interpolated
transform that mixes percentage translation with rotation.
Allow overflow-clip-margin's object-valued Typed OM path to use the
property parser before the value reaches CSSStyleProperties.
CSSKeywordValue("border-box") otherwise arrived as a bare keyword for
a shorthand, tripping the shorthand expansion guard.
Keep the normalization scoped to the overflow-clip-margin shorthand
family so existing Typed OM shorthand behavior remains unchanged. Add
a crash test for the keyword and length forms from the WPT coverage.
Resolve connected @font-face font-width descriptors with the rule's
document context before updating the cached width used for font
selection. This matches the font-style and font-weight descriptor
handling and lets relative units inside calculations simplify safely.
Add crash coverage for an @font-face font-width descriptor using
sign() with rem units.
safe and unsafe are <overflow-position> modifiers per css-align-3
and must accompany an alignment value. Reject them as standalone
keywords for align-items, align-self, justify-items and
justify-self.
The check only applies when these properties are parsed as
longhands; their use inside the place-items and place-self
shorthands goes through a separate code path and is unaffected.
`@scope (a) to (b) {}` applies its contained style rules to elements
that have `a` as a parent, and do not have `a b` as a parent. Both the
`a` and `b` selector lists are optional.
Because it's situational whether a `@scope` will apply to a given
element, we store the ancestor scope on the `MatchingRule`, similar to
`@container`, and then determine during matching whether all the parent
`@scope`s match or not.
The rules for how selectors inside `@scope` are adjusted and interpreted
are a bit confusing. Unlike for other at-rules, nested style rules
inside `@scope` do not get a leading `&` added during parsing. To
support this, `adapt_nested_relative_selector_list()` now takes a flag
for whether its parent is a `@scope` or not.
`@scope` can also contain nested declarations without itself being
nested inside a style rule.
When determining their selectors, nested declarations rules adopt the
`@scope`'s scoping root if it has one, or otherwise fall back to the
parent element of the `<style>` element (not implemented here,) or the
`:root`. These are required to have zero specificity, so we wrap the
selector in `:where()`.
This is preparation for nested declarations inside `@scope`. User code
no longer makes assumptions about there being a style rule parent, as
there may not be one.
We cache the absolutized selectors because `@scope` will require us to
modify the parent's selectors instead of using them directly.
Specifically we will need to know the parent rules for a nested style
rule inside `@scope` in order to resolve its selectors correctly.
Reusing our existing m_rule_context stack is the simplest option - once
we reach the point of converting rules, this context stack is empty, so
we can populate it as we go.
We previously just ignored `&` when absolutizing it would become
`:scope`, because of specificity, but we can actually directly replace
it with `:where(:scope)` in that situation instead.
This commit also renames parent_style_rule() to nesting_parent_rule()
and it doesn't just return CSSStyleRules - in a later commit, we'll
also detect CSSScopeRules here.
Once we implement `@scope`, the rule used as the parent for nesting
selectors won't always be a style rule, but could be a `@scope` rule.
This will get adjusted once those are added.
Just a move with very minor adjustments. We're going to need to run the
absolutization process on other selectors besides those in a
CSSStyleRule - specifically the scope target of CSSScopeRule. So put the
code where it's accessible.
Matches if we support the at-rule in some form.
Keeping this list up to date is a bit awkward, but we don't add at-rules
too often, and having all at-rules defined in JSON would just move the
awkward-to-maintain list somewhere else.
Track explicit inherit of non-inherited properties only on the direct
parent shadow root. A deeper descendant with margin-left: inherit still
inherits from its own parent, so a host margin change does not require
marking every ancestor as possibly affected.
Extend the shadow-root inherited style test to cover both the direct
child case that must still update and the deeper descendant case that
must not trigger broad inherited-style recomputation.
Make style updates reach a fixed point when slot invalidation dirties
assigned nodes after their traversal point. During inherited-style
cascades, only the topmost changed element scans for descendant slots.
Animation inherited-style updates now include the target slot and walk
shadow-including descendants, so host animations propagate inherited
values through shadow trees and assigned slottables. Animated inherited
longhands also carry the same inherited-style invalidation signal as
regular style changes.
Mark custom elements dirty when their :defined state flips, so upgraded
elements do not keep stale :not(:defined) computed style. Add coverage
for slotted menu invalidation, descendant-slot scan counts, target slot
animations, host shadow-tree animations, and explicit inherit from an
animated non-inherited longhand.
Track when style recomputation may require inherited-style work in a
shadow tree, and use that signal when crossing from a shadow host into
its shadow root. Shadow descendants can explicitly inherit normally
non-inherited host properties, so any host style change may need
inherited-style recomputation there.
Use the CSS property definition to tell whether changed longhands need
to propagate to shadow descendants. Do the same after recomputing
inheritance-dependent values, such as host font-size: 2em after a parent
font-size change.
The shadow DOM tests cover inline and class-driven inherited host style
changes, explicit inherit for non-inherited host properties, relative
units on hosts, and nested slotted inheritance updates.
Split cosmetic blocker rules out from network patterns. Expose matching
rules as user CSS through StyleScope.
Invalidate affected user style caches when blocker state changes.
Generated cosmetic CSS now respects disabled content blocking.
Parameter values are absolutized at style computation time (or are
confirmed to be resolvable in the case of reification or DOMMatrix) so
there is no reason this function should fail.
All relative lengths will have been absolutized at style computation
time (or disallowed at parse time in the case of DOMMatrix) so we don't
need to resolve them again here.