Store CSS token payloads in a variant so each token only carries the
state needed by its type. Keep delimiter, number, hash, string, and
dimension data separate instead of storing every possible payload on
every token.
Use a smaller component-value token for function and block boundary
metadata. These component values only need token type, original source
text, and source positions, so avoid embedding full token payload
storage inside every Function and SimpleBlock.
Shrink CSS source positions to explicit 32-bit counters. Guard the C++
and Rust tokenizer paths against overflow. Add size assertions for the
hot Token and ComponentValue types so future growth is intentional.
Separate MediaQueryList change reporting from stylesheet media rule
invalidation. Creating matchMedia() objects evaluates their own baseline
state, but should not make the next style update walk all active
stylesheets when the media environment has not changed.
This avoids continuous stylesheet media query reevaluation during
YouTube video playback, where repeated matchMedia() creation can make
style flushes do unnecessary work.
Add Internals.deleteAllCookies(), backed by an async WebContent to
browser request and ack pair. CookieJar can now clear transient and
persisted cookies. Note that we only delete all cookies associated
with the current URL so that tests are able to run in parallel with
one another without impacting shared cookie state.
LibWeb's WebGL implementation currently reaches ANGLE by calling glFoo()
throughout the WebGL context and extension code. That ties the WebGL
spec layer to the concrete GL executor. A future backend that records
operations, sends them to another process, or executes them from the
Compositor would otherwise need to duplicate the WebGL logic or edit
every call site again.
Introduce GLFunctions as an explicit boundary between WebGL semantics
and GL execution. GLFunctions.json lists the GL entry points used by the
implementation, and the generator emits one forwarding method per entry
point. OpenGLContext implements those methods today, so the current
in-process ANGLE path keeps the same behavior while all callers go
through a single replaceable interface.
That boundary is needed before canvas/WebGL rendering can move to the
Compositor: the WebGL context code can keep doing validation, state
tracking, and spec-visible error handling in LibWeb, while a later
implementation can record the same GL calls and replay them where the
canvas surface is produced. The JSON source also gives the recorder and
replayer one shared description of argument shapes, avoiding two
hand-written views of the GL API drifting apart.
Mach transport already sends payloads as out-of-line virtual-copy
regions, but the receive path immediately copied each payload into a new
Vector and deallocated the kernel mapping. That made the IPC IO thread
touch every byte before the main thread could decode the message.
Add ReceivedMessageBytes as the raw-message byte storage and let the
Mach transport adopt the OOL region directly. The mapping now lives
until the raw message storage is destroyed, so invalid descriptor paths
and normal queue teardown both release it through the same destructor.
Socket transports keep their existing receive copy path by wrapping
vectors in the same storage type, and the direct raw-message consumers
now decode from its ReadonlyBytes view.
MessageBuffer::transfer_message() handed a MessageDataType to transport
APIs that accepted Vector<u8> const&. That forced the inline-capacity
vector to be materialized as a plain Vector<u8>, and the Mach transport
then copied the same payload again into its pending-send queue.
Make the transport API take MessageDataType by value and pass the
encoded buffer with take_data(). The Mach pending queue now stores the
same type so the payload can move directly to the IO thread. The socket
transport keeps queued messages as owned headers plus moved payloads
instead of copying the payload into an AllocatingMemoryStream, while
preserving the existing chunked send and fd acknowledgement behavior.
The pragma directives specification steps should only run when a meta
element is inserted into the document, meaning it is in a document tree
after the insertion steps have run. We previously ran the pragma
algorithms for any insertion, so inserting a meta element with
`http-equiv=content-language` into a detached subtree dereferenced a
null document element.
Hide the native Vulkan child window whenever the current paintable
cannot be imported and rendered through the dmabuf path. This lets the
existing QWidget paint path remain visible for shareable bitmap frames
instead of covering it with a clear-only Vulkan frame.
Make the address autocomplete popup a non-activating top-level window.
The Linux Vulkan web view is a native child window, so ordinary widgets
that overlap it can be obscured by native stacking. Keeping the popup as
a top-level tooltip-style window lets it appear above web content while
preserving keyboard focus in the location edit.
Use a native QVulkanWindow child for Linux DMABUF presentation instead
of making WebContentView itself a QRhiWidget. This keeps BrowserWindow
on Qt's normal QWidget backing store path while sampling compositor
DMABUF backing stores directly in Vulkan.
Keep WebContentView's paintEvent as fallback for builds without Vulkan
DMABUF support and for cases where the Vulkan instance or window cannot
be created. Set an explicit Vulkan API version before creating the
shared QVulkanInstance so validation layers do not reject Qt defaults.
Keep the Linux DMABUF handle alongside the bitmap wrapper when imported
shared images reach the UI process. This lets consumers import the same
GPU backing store directly instead of only reading it through the mapped
bitmap.
Also require exported Vulkan shared images to be sampleable, since the
Qt Vulkan presentation path needs to sample compositor backing stores.
SDL enumerates connected input devices through libudev whenever a
device is added or removed, which probes per-device metadata using
`faccessat2` and `fstatfs`. These calls run after the seccomp filter is
installed, and neither syscall was permitted, so connecting a gamepad
killed the WebContent process with SIGSYS. We now permit `faccessat`
alongside `faccessat2` because glibc's `faccessat` wrapper falls back
to it on kernels without `faccessat2`.
Keep the non-subject :has() affected bit across element style
recomputation. This bit can be discovered while matching descendant
selectors, and recomputing the anchor itself may not revisit those
selectors before a later mutation needs the dependency for targeted
:has() invalidation.
This avoids stale descendant style after targeted :has() invalidation
when a previous recompute cleared the anchor-side dependency metadata.
Repeated style invalidation tests cover the previously flaky case.
Property invalidation inside :nth-child(... of ...) used to become a
whole-subtree invalidation plan. That is broader than needed for
property changes that only affect the filtered sibling list, such as
:has() becoming true or false for one sibling.
Add an invalidation plan bit that marks the element and structurally
affected siblings instead. Keep whole-subtree invalidation when a
stronger plan already requires it, and cover both :nth-child and
:nth-last-child filters with :has() regression tests.
Use structural-position pseudo-classes as subject match filters while
building style invalidation plans. Selectors such as `.menu:has(> .flag)
> :first-child` can then carry a concrete right-hand match set instead
of widening the `:has()` invalidation plan to the whole subtree.
Keep these pseudo-classes out of trigger-property sets since structural
topology mutations are handled separately. This avoids adding unrelated
cold topology recomputes while still letting the affected boundary
children be invalidated directly.
Add a regression test that mutates the child class used by `:has()` and
asserts that the old whole-subtree path does not produce excessive no-op
style recomputations.
Feature-filter :not() arguments in :has() when the same compound also
has a concrete tag, id, class, or attribute selector. Bare negations
still stay conservative, but anchored negations no longer make unrelated
subtree mutations walk every :has() candidate.
Also avoid installing the whole-subtree :has() fallback for rightmost
complex :is()/:where() arguments that only use descendant or child
combinators. Keep the fallback for non-rightmost and sibling-combinator
cases where the existing plan cannot represent the nested selector
context.
Add counter-based style invalidation coverage for both cases.
Record hover, focus, focus-visible, focus-within, and target pseudo
classes in :has() invalidation metadata. This lets the existing
property invalidation path schedule :has() ancestor invalidation only
for scopes whose :has() selectors mention the changed pseudo-class.
Interaction pseudo-class invalidation previously scheduled :has()
ancestor invalidation for every style scope containing any :has()
selector. That kept selectors like .wrapper:has(:focus) * correct, but
also caused unrelated hover and focus changes to fan out through broad
:has() descendant invalidation rules.
Update style invalidation coverage so unrelated hover changes avoid the
extra :has() walk, while a descendant :has(:focus) rule still restyles
its affected descendants when focus changes.
Effect culling can stop a visual context switch after applying
some ancestor contexts. The player left those contexts on the painter
stack even though the target command was skipped.
Restore the painter stack back to the common ancestor when effect
culling aborts the switch.
compute_transform() resolved transform-origin to a 2D point, so 3D
rotations pivoted around the element's own plane. Build the conjugation
T(0, 0, z) * M * T(0, 0, -z) into the matrix instead; this composes
with the 2D origin at paint time into the full 3D conjugation.
Now that Badge can have multiple types, and a Badge of a derived class
can convert into a Badge of the superclass, we can simplify a few method
signatures and overloads.
Frames are considered late if the time is ahead by half their duration.
The fudging is necessary because Matroska (and perhaps other formats)
store their frame durations in different time units than their
timestamps.
Skipping these should make it clear when decoding is running behind,
instead of displaying the video in slow motion while audio runs at a
normal rate.
To give an accurate counting for video playback quality when it is
implemented, we'll most likely want to count all pulled frames in an
update as dropped if the last frame is dropped. Otherwise the frame
drop count will only increase at the display rate when decoding is
continually running behind.
This is already handled by the seeking state enum later. We could end
up displaying nothing if MovedPosition isn't immediately followed by a
displayable frame.
When generating global mixins, only define regular members from the
[Global] interface itself on the global object. Inherited members remain
available through the prototype chain.
This was found due to a timeout on:
https://wpt.live/html/dom/idlharness.any.worker.html
Installing inherited members created fresh own functions on worker
globals, so self.importScripts differed from
WorkerGlobalScope.prototype.importScripts. That confused idlharness into
taking its null-this check path for importScripts, which then attempted
to import "null" and timed out.
EventHandler attributes are nullable callback function attributes with
[LegacyTreatNonObjectAsNull]. Assigning a non-object value should
produce null, but assigning an object value should preserve that object
as the callback value, even when the object is not callable.
Previously, object values such as `{ handleEvent() {} }` could pass the
nullable conversion and then be converted to null by the inner callback
function conversion. This made MessagePort.onmessage in the fixed test
return null after such an assignment.
Handle the non-object-to-null rule in nullable conversion, and let the
legacy callback conversion wrap object values without rejecting them for
not being callable.
Fixes a regression in the python port of the IDL generator.
Firefox sends the same storage actor mutation requests for Web Storage
that it uses for cookies. Handle addItem, editItem, removeItem, and
removeAll for localStorage and sessionStorage actors.
Apply the changes through the browser-process storage jar and emit the
matching store update packets so the Storage panel stays current after a
DevTools-initiated edit.
Firefox keeps the Storage panel current by sending store update packets
when localStorage or sessionStorage changes. Forward successful Web
Storage mutations to the storage actors and emit the matching update or
clear packet.
Use listener IDs for storage updates so the local and session storage
actors can subscribe independently.
Firefox exposes localStorage and sessionStorage through the same
storage actor protocol used by cookies. Add matching resources for the
current tab so the Storage panel can list key/value pairs.
Read the values through WebContent rather than directly from the
browser process. Session storage lives in LibWeb, and using the same
path for both stores keeps the actor independent of the backing store.
Propagate the CORS-cross-origin state from image fetch responses through
SharedResourceRequest, ImageRequest, and the available image cache.
Use that state when drawing HTML images to canvas so cross-origin image
data taints the canvas correctly.
Initialize the imported WPT server with the dynamic test HTTP port and
localhost-backed host aliases so .sub.html files can expand {{host}},
{{ports}}, and {{domains[...]}} during LibWeb text tests.
Firefox enables the Storage panel cookie toolbar from the storage traits
and calls addItem, removeItem, removeAll, or removeAllSessionCookies
for the selected host.
Advertise those operations and route them through the existing cookie
mutation delegate. Deletions reuse the visible storage host matching so
bulk actions stay scoped to the cookie tree item Firefox selected.