Commit Graph

77529 Commits

Author SHA1 Message Date
Andreas Kling
c919f1c28f LibWebView: Add style invalidation counter dump option
Add --dump-style-invalidation-counters=N to Ladybird and propagate it
to WebContent helper processes.

When enabled, WebContent dumps the current document style invalidation
counters with dbgln() after every N recorded style invalidations. This
makes it possible to collect the counters while browsing without adding
temporary C++ logging.
2026-04-30 00:24:04 +02:00
Aliaksandr Kalenik
f785e13ae9 LibWeb: Schedule rendering updates on demand
Previously a fixed-rate paint refresh timer kept queueing rendering
update tasks at the maximum configured frame rate, regardless of whether
anything had actually changed. This wasted CPU on idle pages, which
spend most of their time in a steady state where no style, layout, or
paint work is needed.

Replace the repeating timer with a single-shot frame timer driven by
PageClient::request_frame(). A rendering update is now scheduled only
when something requires one. The configured maximum frame rate is
preserved as a ceiling on how closely consecutive frames can follow each
other.
2026-04-29 20:54:53 +02:00
Jelle Raaijmakers
1aeb080250 LibCompress: Treat LZW decoding errors as end of stream
The LZW data for both GIF and TIFF images is sometimes intentionally
missing an end-of-information (EOI) code, which technically is a
decoding error, but in practive is handled gracefully by Firefox, Safari
and Chrome for GIFs and Safari for TIFFs. Let's mirror their behavior.

The included WPT test exposes the fact that trailing garbage bytes can
also result in decoding errors. We handle this in the LZW logic rather
than in the image decoding since our LZW implementation is currently
only used by GIF and TIFF decoding. The error is logged behind the
LZW_DEBUG flag.
2026-04-29 20:28:15 +02:00
Jelle Raaijmakers
d8ad66d95d Tests/LibWeb: Dispatch TestRendered event when reftest-wait is present
This furthers our compatibility with WPT tests.
2026-04-29 20:28:15 +02:00
Jelle Raaijmakers
71b0aaa461 AK: Simplify BigEndianInputBitStream::read_bits()
No need to perform extra loop iterations every time we need to read a
new byte. No functional changes.
2026-04-29 20:28:15 +02:00
Jelle Raaijmakers
3ffc75961d LibCompress: Mark right Lzw constructors as explicit 2026-04-29 20:28:15 +02:00
Jelle Raaijmakers
9ee690ba0e AK: Remove unused #includes from BitStream.h 2026-04-29 20:28:15 +02:00
Sam Atkins
f242bee7f3 Meta: Replace GenerateNamedCharacterReferences with a python generator
This is a direct conversion, and produces the same output.
2026-04-29 17:28:09 +01:00
Sam Atkins
7a7b838ed5 Meta: Replace GenerateAriaRoles with a python generator
This is a direct conversion, and produces the same output.
2026-04-29 17:28:09 +01:00
Aliaksandr Kalenik
b88cbb1b74 LibWeb: Have speculative HTML parser populate the preload map
When the regular HTML parser is blocked on an external script, the
speculative parser scans ahead and pre-fetches discoverable
sub-resources. Previously those fetches were tracked only in the
parser's own URL list and never registered in the document's preload
map, so when the regular parser later reached each element fetch()'s
consume_a_preloaded_resource() lookup found nothing and issued a
duplicate request — every parser-blocked sub-resource was fetched
twice.

issue_speculative_fetch now creates a PreloadEntry, registers it
under create_a_preload_key(request) in the document's preload map,
and supplies a processResponseConsumeBody callback that populates
the entry. The map insertion happens after fetch() starts because
fetch() runs consume_a_preloaded_resource() synchronously, so
registering the entry beforehand would short-circuit the
speculative fetch itself.

The body-handling steps (1, 2, 5 of the preload algorithm's
processResponseConsumeBody) are factored into a shared
deliver_preload_response helper used by both the speculative parser
and HTMLLinkElement::preload.
2026-04-29 15:59:22 +02:00
Andreas Kling
09aefc2cd5 LibWeb: Move embedded content style invalidation into a helper
IFrame geometry changes and object representation changes directly
selected style invalidation reasons from their HTML element classes.
Move those mappings into a new
CSS::Invalidation::EmbeddedContentInvalidator.

The HTML elements continue to own their loading, representation, and
layout-tree side effects. CSS invalidation now owns the style dirtiness
associated with those embedded-content changes.
2026-04-29 15:47:23 +02:00
Andreas Kling
007dc28d16 LibWeb: Move shadow root style invalidation into the helper
Element::set_shadow_root directly selected the style invalidation reason
used when a shadow root changes. Move that mapping into
CSS::Invalidation::ElementStateInvalidator.

Element still owns the shadow-root state transition and the required
layout-tree invalidation. CSS invalidation now owns the style dirtiness
for that state change.
2026-04-29 15:47:23 +02:00
Andreas Kling
b0bb2bd0a8 LibWeb: Move active state invalidation into the helper
Element::set_being_activated directly selected the style invalidation
reason used for :active changes. Move that mapping into
CSS::Invalidation::ElementStateInvalidator.

The element continues to own its activation state. CSS invalidation now
owns the style invalidation work associated with changing that state.
2026-04-29 15:47:23 +02:00
Andreas Kling
ca08d5a901 LibWeb: Move custom state set invalidation into the helper
CustomStateSet directly selected the style invalidation reason used when
its JS-visible set is modified. Move that mapping into
CSS::Invalidation::CustomElementInvalidator.

This keeps the custom-state container focused on its set contents while
CSS invalidation owns the style work required by :state() selectors.
2026-04-29 15:47:23 +02:00
Andreas Kling
83dfed14ad LibWeb: Move input open style invalidation into the helper
HTMLInputElement still mapped its picker open-state change directly to a
style invalidation reason. Move that mapping into
CSS::Invalidation::ElementStateInvalidator alongside the matching select
open-state helper.

This keeps another element-state invalidation decision out of the HTML
implementation without changing the invalidation behavior.
2026-04-29 15:47:23 +02:00
Andreas Kling
c93dad7600 LibWeb: Move element state style invalidation into a helper
Several HTML element state changes directly selected style invalidation
reasons from their element implementations. Move those mappings into a
new CSS::Invalidation::ElementStateInvalidator helper.

This keeps details, dialog, option, and select code focused on their own
state changes while CSS invalidation owns the style work those changes
require. The existing invalidation breadth is preserved.
2026-04-29 15:47:23 +02:00
Andreas Kling
79c32f88d2 LibWeb: Move pending :has() invalidation into the helper
Document.cpp still flushed pending :has() invalidation by walking the
document and shadow-root style scopes directly. Move that CSS-specific
flush into CSS::Invalidation::HasMutationInvalidator.

Document continues to own the flag that says a :has() flush is needed.
The helper now owns the style-scope work needed to invalidate elements
affected by pending :has() mutations.
2026-04-29 15:47:23 +02:00
Andreas Kling
b8c2469566 LibWeb: Move media query style invalidation into a helper
Document.cpp still handled CSS fallout from stylesheet media query match
changes directly. Move active stylesheet evaluation, rule-cache
invalidation, shadow-root fallout, and slot propagation into the CSS
invalidation helper.

Document continues to decide when media queries should be evaluated.
The helper now owns the style invalidation consequences when stylesheet
media queries change match state.
2026-04-29 15:47:23 +02:00
Andreas Kling
0a938fdd51 LibWeb: Move slot style propagation into the helper
Document.cpp still knew how style changes on a slot propagate to
assigned light-DOM nodes. Move that flat-tree inheritance invalidation
into CSS::Invalidation::SlotInvalidator.

The style update walk continues to decide when an element's style
changed. The helper now owns the ::slotted() consequence of dirtying
assigned slottables for a changed slot.
2026-04-29 15:47:23 +02:00
Andreas Kling
98b13da3b4 LibWeb: Move adopted stylesheet invalidation into a helper
AdoptedStyleSheets.cpp still handled CSS-side fallout from adopted sheet
list mutations directly. Move sheet attachment and media-query setup to
a CSS invalidation helper, along with rule-cache invalidation.

The observable array callbacks continue to validate JS values and
same-document construction rules. The helper now owns the CSS work for
when a constructed stylesheet becomes visible to, or is removed from, a
Document or ShadowRoot.
2026-04-29 15:47:23 +02:00
Andreas Kling
c191d51af1 LibWeb: Move slotted style invalidation into a helper
Slottable.cpp still handled the style invalidation fallout from slot
assignment changes directly. Move that ::slotted()-related policy into
CSS::Invalidation::SlotInvalidator.

Slot assignment remains DOM bookkeeping. The helper now owns the
choice to dirty element slottables when they gain or lose assignment
to a slot.
2026-04-29 15:47:23 +02:00
Andreas Kling
bc0059cfd5 LibWeb: Move text directionality invalidation into the helper
CharacterData.cpp still handled the style invalidation fallout from text
mutations under dir=auto ancestors directly. Move that behavior into the
CSS language invalidation helper.

CharacterData continues to own text replacement and layout text updates.
The helper now owns the inherited :dir() restyle and :has(:dir(...))
ancestor scheduling that can follow from text content changes.
2026-04-29 15:47:23 +02:00
Andreas Kling
1ba3ec6ae7 LibWeb: Move part style invalidation into a helper
Element.cpp still handled the style invalidation fallout from part and
exportparts attribute changes directly. Move that ::part-related policy
into CSS::Invalidation::PartInvalidator.

Element continues to update the DOM token state for part attributes. The
helper now owns the style dirtiness for elements targeted through ::part
and for shadow-tree descendants exposed through exportparts.
2026-04-29 15:47:23 +02:00
Andreas Kling
b0effb3167 LibWeb: Move language style invalidation into a helper
Element.cpp still handled the CSS invalidation fallout from dir and lang
attribute changes directly. Move the descendant style dirtiness and
:has(:dir/:lang) ancestor scheduling into CSS::Invalidation.

Element continues to parse and store the DOM-facing attribute state. The
new helper owns the inherited style invalidation behavior that follows
from language and directionality changes.
2026-04-29 15:47:23 +02:00
Andreas Kling
3d8fa1ed26 LibWeb: Move node style invalidation into a helper
Node.cpp still contained the CSS policy for full style invalidation and
property-based invalidation plans. Move that logic into
CSS::Invalidation::NodeInvalidator.

Node remains the public DOM entry point for callers that need to
invalidate style. The helper now owns the :has() metadata probing,
style-scope plan lookup, and subtree/sibling invalidation scheduling.
2026-04-29 15:47:23 +02:00
Andreas Kling
61a18d91d6 LibWeb: Move pseudo-class state invalidation into a helper
Document.cpp contained the CSS rule-cache matching used to decide which
elements need style updates when hover, focus, or target state changes.
Move that logic into CSS::Invalidation::PseudoClassInvalidator.

Document still owns the current state slots and chooses when a state
transition happens. The helper now owns the selector matching and
recursive invalidation pass for those pseudo-class transitions.
2026-04-29 15:47:23 +02:00
Andreas Kling
6069bcdcc7 LibWeb: Move StyleInvalidator into CSS invalidation
StyleInvalidator applies CSS invalidation plans and matches selector
features while walking DOM nodes. Move the class from DOM into the
CSS::Invalidation namespace alongside the other invalidation helpers.

Document still owns the invalidator and DOM nodes still expose the state
that gets marked, but the policy for applying invalidation plans now has
a home with the rest of the CSS invalidation code.
2026-04-29 15:47:23 +02:00
Andreas Kling
4b3abc6958 LibWeb: Move invalidation set matching into a helper
Element.cpp still contained the CSS logic for deciding whether an
invalidation set references features present on an element. Move that
matcher into CSS::Invalidation::InvalidationSetMatcher.

The helper uses Element's public API for classes, id, attributes,
pseudo-class state, and removed-attribute tracking. This keeps Element
focused on DOM state while CSS::Invalidation owns selector feature
matching.
2026-04-29 15:47:23 +02:00
Andreas Kling
d7f5939e46 LibWeb: Move custom element state invalidation into a helper
Element.cpp still spelled out the :defined pseudo-class invalidation set
when custom element state changed. Move that selector policy into
CustomElementInvalidator.

This keeps Element responsible for the state transition, while
CSS::Invalidation owns the affected selector feature.
2026-04-29 15:47:23 +02:00
Andreas Kling
7c401b051b LibWeb: Move checked-state invalidation into a helper
HTMLInputElement had two call sites spelling out the same checked and
unchecked pseudo-class invalidation set. Move that selector policy into
FormControlInvalidator.

This keeps the input element responsible for detecting state changes,
while CSS::Invalidation owns the affected selector features.
2026-04-29 15:47:23 +02:00
Andreas Kling
84f4140226 LibWeb: Move hyperlink style invalidation into a helper
HTML and SVG link elements both encoded the same pseudo-class list for
hyperlink state changes. Move that CSS policy into LinkInvalidator and
have both call sites delegate to it.

This keeps element-specific code focused on detecting hyperlink state
changes, while the helper owns the affected selector features.
2026-04-29 15:47:23 +02:00
Andreas Kling
eeab3671c2 LibWeb: Move attribute style invalidation into a helper
Element.cpp still encoded the CSS consequences of attribute changes:
class/id invalidation keys, pseudo-class triggers, and shadow-host
stylesheet fallout. Move that policy into AttributeInvalidator.

Element now reports attribute changes to the helper and exposes a small
state hook to remember removed attributes while invalidation is pending.
2026-04-29 15:47:23 +02:00
Andreas Kling
85e33738f5 LibWeb: Move :has() element invalidation into the helper
Element exposed a small method that encoded how :has()-affected elements
are marked dirty. Move that policy into CSS::Invalidation alongside the
rest of the :has() mutation invalidation helpers.

This keeps Element focused on DOM state while preserving the existing
subject and non-subject :has() invalidation behavior.
2026-04-29 15:47:23 +02:00
Andreas Kling
95eb41092c LibWeb: Move structural mutation invalidation into a helper
Node.cpp still contained selector-specific policy for sibling and
same-parent-move structural invalidation. Move that logic into
CSS::Invalidation::StructuralMutationInvalidator so DOM mutation code
can delegate structural selector dependency handling.

This is a behavior-preserving extraction. It keeps the existing
previous-sibling walk guard, sibling-distance checks, shadow-root
marking, and ancestor child-needs-style propagation.
2026-04-29 15:47:23 +02:00
Andreas Kling
e4e3c46837 LibWeb: Move :has() mutation scheduling into a helper
Node.cpp still contained the policy for deciding when a DOM mutation
should schedule pending :has() invalidation work. Move that into
CSS::Invalidation::HasMutationInvalidator, next to the mutation feature
collector it depends on.

This keeps DOM mutation code focused on reporting that a mutation
happened, while CSS invalidation code owns the selector-specific checks
for :has() metadata and sibling-combinator sensitivity.
2026-04-29 15:47:23 +02:00
Andreas Kling
ea64c5e147 LibWeb: Move :has() mutation checks into a helper
Node.cpp currently knows too much about selector invalidation metadata
when deciding whether subtree mutations can affect :has() selectors.
Pull that logic into CSS/Invalidation/HasMutationFeatureCollector so DOM
mutation code can ask a focused helper instead of inspecting
StyleInvalidationData directly.

This is a behavior-preserving extraction. It keeps the existing
conservative fallbacks for featureless subtree-sensitive selectors and
still uses the existing element property matching helper for
pseudo-class metadata.
2026-04-29 15:47:23 +02:00
Andreas Kling
c9cac66677 Tests: Expand style invalidation coverage
Add broader style-invalidation regression coverage for selector shapes
that are easy to mis-model when invalidation data is flattened into
feature sets. Cover selector-list alternatives, nested pseudo-class
arguments, pseudo-element arguments, nth-child selector lists,
quirks-mode class matching, mixed-case ancestor filters, duplicate
invalidation rule merging, and concrete :has() feature filtering.

Keep the expectations on the unoptimized baseline so follow-up
optimization commits can show the counter progressions separately.
These tests dump the normal invalidation counters instead of asserting
specific counter values in script.
2026-04-29 15:47:23 +02:00
Sam Atkins
39c997b102 Meta: Use consume_specific in Python CSS Grammar tokenizer
A stealth merge conflict meant consume_specific_string() and
consume_specific_char() got combined into a single method and no longer
exist.
2026-04-29 13:23:53 +01:00
Shannon Booth
6cd7425a4b Meta: Port GenerateWindowOrWorkerInterfaces to Python
This replaces the C++ GenerateWindowOrWorkerInterfaces generator with a
python3 port.

The generator uses the new python WebIDL parser and writes directly to a
TextIO instance instead of porting SourceGenerator.

For validation, the python generator was diffed against the existing C++
generator over the full LibWeb IDL input set. The generated output is
behaviorally identical, and the only changes are whitespace changes
(all improvements).
2026-04-29 12:24:00 +01:00
Shannon Booth
6fc06afc81 Meta: Add a Python WebIDL parser
Add a simple python3 WebIDL parser for the subset of IDL we need for
code generation.

For validation, the parser structure is intentionally very close to the
existing C++ parser, so the control flow and parsing mechanics stay easy
to compare while we continue porting IDL-related generators.

This parser currently focuses on the constructs needed by
GenerateWindowOrWorkerInterfaces, but is meant to serve as a base for
future IDL generator ports as well.
2026-04-29 12:24:00 +01:00
Shannon Booth
af5290b41b Meta: Extend the python lexer with some more APIs
Add a few GenericLexer-style helpers to lexer.py:

* tell()
* ignore()
* next_is()
2026-04-29 12:24:00 +01:00
Shannon Booth
4a9deb3afa Meta: Combine Lexer's consume_specific_char and consume_specific_string
consume_specific_string() already handles 1-character strings correctly.
2026-04-29 12:24:00 +01:00
Callum Law
66c10ed190 LibWeb: Generate `<font-weight-absolute> parsing 2026-04-29 11:42:57 +01:00
Callum Law
0d75d66f2e Meta: Handle bracketed range notations in CSS value grammar 2026-04-29 11:42:57 +01:00
Callum Law
521beb5a96 Meta: Implement code generation for CSS keyword values 2026-04-29 11:42:57 +01:00
Callum Law
9a3f2b23a1 LibWeb: Add method to parse specific CSS keyword
This revealed an issue with `@counter-style/range` where parsing could
consume and ignore invalid keywords
2026-04-29 11:42:57 +01:00
Callum Law
44ad7e30b4 LibWeb: Generate <symbol> parsing 2026-04-29 11:42:57 +01:00
Callum Law
dd9f0b8838 Meta: Implement code generation for CSS custom ident value blacklists 2026-04-29 11:42:57 +01:00
Callum Law
09418e8c77 Meta: Implement CSS value type parsing code generation
To do this we parse the grammar supplied in `ValueTypes.json` and
generate the appropriate parsing function in `CSS::Parser::Parser`

Only a small subset of the CSS grammar (i.e. types `<foo>` and
alternatives `<foo> | <bar>`) is implemented so far, it will be
expanded in later commits.
2026-04-29 11:42:57 +01:00
Callum Law
8849435d6f Meta+LibWeb: Initial scaffolding for CSS value type parsing code gen
In the future we should switch to using a better file format for this,
i.e. one that supports directly pasting CSS grammar production blocks
(https://drafts.csswg.org/css-values-4/#css-grammar-production-block)
and has support for inline comments, but we use JSON for now for
simplicity's sake.
2026-04-29 11:42:57 +01:00