Igalia worked with Savant Systems to bring a seamless, high-performance music experience to its smart home ecosystem. By enhancing WPE WebKit with critical backported patches, developing a custom Widevine CDM, and engineering a JavaScript D-Bus bridge, WPE WebKit was adapted to ensure robust and secure media playback directly within Savantโs platform.
Delivering a tightly integrated music experience in a smart home environment required overcoming significant technical challenges. To achieve this, WPE WebKitโs capabilities were streamlined to enable a fluid interface and reliable communication between the browser and the music process that powers a third-party music integration.
With deep expertise in browser technology and embedded systems, Igalia was able to help Savant implement a tailored WPE WebKit integration, optimizing performance while maintaining security and responsiveness. The result is a cutting-edge solution that enhances user experience and supports Savantโs commitment to innovation in smart home entertainment.
Update on what happened in WebKit in the week from May 12 to May 19.
This week focused on infrastructure improvements, new releases that
include security fixes, and featured external projects that use the
GTK and WPE ports.
Cross-Port ๐ฑ
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Fixed
a reference cycle in the mediastreamsrc element, which prevented its disposal.
JavaScriptCore ๐
The built-in JavaScript/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.
Added an internal class that will be
used to represent Temporal Duration objects in a way that allows for more
precise calculations. This is not a user-visible change, but will enable future
PRs to advance Temporal support in JSC towards completion.
WPE WebKit ๐
WPE Platform API ๐งฉ
New, modern platform API that supersedes usage of libwpe and WPE backends.
Added
an initial demo application to the GTK4 WPEPlatform implementation.
Releases ๐ฆ๏ธ
WebKitGTK
2.48.2 and
WPE WebKit 2.48.2 have
been released. These are paired with a security advisory (WSA-2025-0004:
GTK,
WPE), and therefore it is
advised to update.
On top of security fixes, these release also include correctness fixes, and
support for CSS Overscroll
Behaviour
is now enabled by default.
Community & Events ๐ค
GNOME Web has
gained a
preferences page that allows toggling WebKit features at run-time. Tech Preview
builds of the browser will show the settings page by default, while in regular
releases it is hidden and may be enabled with the following command:
gsettings set org.gnome.Epiphany.ui webkit-features-page true
This should allow frontend developers to test upcoming features more easily. Note that the settings for WebKit features are not persistent, and they will be reset to their default state on every launch.
Infrastructure ๐๏ธ
Landed an improvement to error
reporting in the script within WebKit that runs test262 JavaScript tests.
The WebKit Test Runner (WKTR) will no longer
crash if invalid UTF-8 sequences
are written to the standard error stream, (e.g. from 3rd party libraries'
debugging options.
Experimentation is ongoing to un-inline String::find(), which saves ~50 KiB
in the resulting binary size worth of repeated implementations of SIMD โfind
character in UTF-16โ and โfind character in UTF-32โ algorithms. Notably, the
algorithm for โfind character in ASCII stringโ was not even part of the
inlining.
Added the LLVM
repository to the
WebKit container SDK. Now it is possible to easily install Clang 20.x with
wkdev-setup-default-clang --version=20.
Figured out that a performance bug related to jump threading optimization in
Clang 18 resulted in a bottleneck adding up to five minutes of build time in
the container SDK. This may be fixed by updating to Clang 20.x.
Update on what happened in WebKit in the week from May 5 to May 12.
This week saw one more feature enabled by default, additional support to
track memory allocations, continued work on multimedia and WebAssembly.
Cross-Port ๐ฑ
The Media Capabilities API is now enabled by default. It was previously available as a run-time option in the WPE/WebKitGTK API (WebKitSettings:enable-media-capabilities), so this is just a default tweak.
Landed a change that integrates malloc heap breakdown functionality with non-Apple ports. It works similarly to Apple's one yet in case of non-Apple ports the per-heap memory allocation statistics are printed to stdout periodically for now. In the future this functionality will be integrated with Sysprof.
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Support for WebRTC RTP header extensions was improved, a RTP header extension for video orientation metadata handling was introduced and several simulcast tests are now passing
Progress is ongoing on resumable player suspension, which will eventually allow us to handle websites with lots of simultaneous media elements better in the GStreamer ports, but this is a complex task.
JavaScriptCore ๐
The built-in JavaScript/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.
The in-place Wasm interpreter (IPInt) port to 32-bits has seen some more work.
Fixed a bug in OMG caused by divergence with the 64-bit version. Further syncing is underway.
Releases ๐ฆ๏ธ
Michael Catanzaro has published a writeup on his blog about how the WebKitGTK API versions have changed over time.
Infrastructure ๐๏ธ
Landed some improvements in the WebKit container SDK for Linux, particularly in error handling.
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
The GstWPE2 GStreamer plugin landed in GStreamer
main,
it makes use of the WPEPlatform API. It will ship in GStreamer 1.28. Compared
to GstWPE1 it provides the same features, but improved support for NVIDIA
GPUs. The main regression is lack of audio support, which is work-in-progress,
both on the WPE and GStreamer sides.
JavaScriptCore ๐
The built-in JavaScript/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.
Work on enabling the in-place Wasm interpreter (IPInt) on 32-bits has progressednicely
The JSC tests runner can now guard against a pathological failure mode.
In JavaScriptCore's implementation of
Temporal,
Tim Chevalier fixed the parsing of RFC
9557 annotations in date
strings to work according to the standard. So now syntactically valid but
unknown annotations [foo=bar] are correctly ignored, and the ! flag in an
annotation is handled correctly. Philip Chimento expanded the test suite
around this feature and fixed a couple of crashes in Temporal.
Math.hypot(x, y, z) received a fix for a corner case.
WPE WebKit ๐
WPE now uses the new pasteboard API, aligning it with the GTK port, and enabling features that were previously disabled. Note that the new features work only with WPEPlatform, because libwpe-based backends are limited to access clipboard text items.
WPE Platform API ๐งฉ
New, modern platform API that supersedes usage of libwpe and WPE backends.
Platform backends may add their own clipboard handling, with the Wayland one being the first one to, using wl_data_device_manager.
This continues the effort to close the feature gap between the โtraditionalโ libwpe-based WPE backends and the new WPEPlatform ones.
Community & Events ๐ค
Carlos Garcรญa has published a blog post about the optimizations introduced in
the WPE and GTK WebKit
ports
since the introduction of Skia replacing Cairo for 2D rendering. Plus, there
are some hints about what is coming next.
In my previous post, when I introduced the switch to Skia for 2D rendering, I explained that we replaced Cairo with Skia keeping mostly the same architecture. This alone was an important improvement in performance, but still the graphics implementation was designed for Cairo and CPU rendering. Once we considered the switch to Skia as stable, we started to work on changes to take more advantage of Skia and GPU rendering to improve the performance even more. In this post Iโm going to present some of those improvements and other not directly related to Skia and GPU rendering.
Explicit fence support
This is related to the DMA-BUF renderer used by the GTK port and WPE when using the new API. The composited buffer is shared as a DMA-BUF between the web and UI processes. Once the web process finished the composition we created a fence and waited for it, to make sure that when the UI process was notified that the composition was done the buffer was actually ready. This approach was safe, but slow. In 281640@main we introduced support for explicit fencing to the WPE port. When possible, an exportable fence is created, so that instead of waiting for it immediately, we export it as a file descriptor that is sent to the UI process as part of the message that notifies that a new frame has been composited. This unblocks the web process as soon as composition is done. When supported by the platform, for example in WPE under Wayland when the zwp_linux_explicit_synchronization_v1 protocol is available, the fence file descriptor is passed to the platform implementation. Otherwise, the UI process asynchronously waits for the fence by polling the file descriptor before passing the buffer to the platform. This is what we always do in the GTK port since 281744@main. This change improved the score of all MotionMark tests, see for example multiply.
Enable MSAA when available
In 282223@main we enabled the support for MSAA when possible in the WPE port only, because this is more important for embedded devices where we use 4 samples providing good enough quality with a better performance. This change improved the Motion Mark tests that use 2D canvas like canvas arcs, paths and canvas lines. You can see here the change in paths when run in a RaspberryPi 4 with WPE 64 bits.
Avoid textures copies in accelerated 2D canvas
As I also explained in the previous post, when 2D canvas is accelerated we now use a dedicated layer that renders into a texture that is copied to be passed to the compositor. In 283460@main we changed the implementation to use a CoordinatedPlatformLayerBufferNativeImage to handle the canvas texture and avoid the copy, directly passing the texture to the compositor. This improved the MotionMark tests that use 2D canvas. See canvas arcs, for example.
Introduce threaded GPU painting mode
In the initial implementation of the GPU rendering mode, layers were painted in the main thread. In 287060@main we moved the rendering task to a dedicated thread when using the GPU, with the same threaded rendering architecture we have always used for CPU rendering, but limited to 1 worker thread. This improved the performance of several MotionMark tests like images, suits and multiply. See images.
Update default GPU thread settings
Parallelization is not so important for GPU rendering compared to CPU, but still we realized that we got better results by increasing a bit the amount of worker threads when doing GPU rendering. In 290781@main we increased the limit of GPU worker threads to 2 for systems with at least 4 CPU cores. This improved mainly images and suits in MotionMark. See suits.
Hybrid threaded CPU+GPU rendering mode
We had either GPU or CPU worker threads for layer rendering. In systems with 4 CPU cores or more we now have 2 GPU worker threads. When those 2 threads are busy rendering, why not using the CPU to render other pending tiles? And the same applies when doing CPU rendering, when all workers are busy, could we use the GPU to render other pending tasks? We tried and turned out to be a good idea, especially in embedded devices. In 291106@main we introduced the hybrid mode, giving priority to GPU or CPU workers depending on the default rendering mode, and also taking into account special cases like on HiDPI, where we are always scaling, and we always prefer the GPU. This improved multiply, images and suits. See images.
Use Skia API for display list implementation
When rendering with Cairo and threaded rendering enabled we use our own implementation of display lists specific to Cairo. When switching to Skia we thought it was a good idea to use the WebCore display list implementation instead, since itโs cross-platform implementation shared with other ports. But we realized this implementation is not yet ready to support multiple threads, because it holds references to WebCore objects that are not thread safe. Main thread might change those objects before they have been processed by painting threads. So, we decided to try to use the Skia API (SkPicture) that supports recording in the main thread and replaying from worker threads. In 292639@main we replaced the WebCore display list usage by SkPicture. This was expected to be a neutral change in terms of performance but it surprisingly improved several MotionMark tests like leaves, multiply and suits. See leaves.
Use Damage to track the dirty region of GraphicsLayer
Every time thereโs a change in a GraphicsLayer and it needs to be repainted, itโs notified and the area that changed is included so that we only render the parts of the layer that changed. Thatโs what we call the layer dirty region. It can happen that when there are many small updates in a layer we end up with lots of dirty regions on every layer flush. We used to have a limit of 32 dirty regions per layer, so that when more than 32 are added we just united them into the first dirty area. This limit was removed because we always unite the dirty areas for the same tiles when processing the updates to prepare the rendering tasks. However, we also tried to avoid handling the same dirty region twice, so every time a new dirty region was added we iterated the existing regions to check if it was already present. Without the 32 regions limit that means we ended up iterating a potentially very long list on every dirty region addition. The damage propagation feature uses a Damage class to efficiently handle dirty regions, so we thought we could reuse it to track the layer dirty region, bringing back the limit but uniting in a more efficient way than using always the first dirty area of the list. It also allowed to remove check for duplicated area in the list. This change was added in 292747@main and improved the performance of MotionMark leaves and multiply tests. See leaves.
Record all dirty tiles of a layer once
After the switch to use SkPicture for the display list implementation, we realized that this API would also allow to record the graphics layer once, using the bounding box of the dirty region, and then replay multiple times on worker threads for every dirty tile. Recording can be a very heavy operation, specially when there are shadows or filters, and it was always done for every tile due to the limitations of the previous display list implementation. In 292929@main we introduced the change with improvements in MotionMark leaves and multiply tests. See multiply.
MotionMark results
Iโve shown here the improvements of these changes in some of the MotionMark tests. I have to say that some of those changes also introduced small regressions in other tests, but the global improvement is still noticeable. Here is a table with the scores of all tests before these improvements and current main branch run by WPE MiniBrowser in a RaspberryPi 4 (64bit).
Test
Score July 2024
Score April 2025
Multiply
501.17
684.23
Canvas arcs
140.24
828.05
Canvas lines
1613.93
3086.60
Paths
375.52
4255.65
Leaves
319.31
470.78
Images
162.69
267.78
Suits
232.91
445.80
Design
33.79
64.06
Whatโs next?
Thereโs still quite a lot of room for improvement, so we are already working on other features and exploring ideas to continue improving the performance. Some of those are:
Damage tracking: this feature is already present, but disabled by default because itโs still work in progress. We currently use the damage information to only paint the areas of every layer that changed. But then we always compose a whole frame inside WebKit that is passed to the UI process to be presented on screen. Itโs possible to use the damage information to improve both, the composition inside WebKit and the presentation of the composited frame on the screen. For more details about this feature read Pawelโs awesome blog post about it.
Use DMA-BUF for tile textures to improve pixel transfer operations: We currently use DMA-BUF buffers to share the composited frame between the web and UI process. We are now exploring the idea of using DMA-BUF also for the textures used by the WebKit compositor to generate the frame. This would allow to improve the performance of pixel transfer operations, for example when doing CPU rendering we need to upload the dirty regions from main memory to a compositor texture on every composition. With DMA-BUF backed textures we can map the buffer into main memory and paint with the CPU directly into the mapped buffer.
Compositor synchronization: We plan to try to improve the synchronization of the WebKit compositor with the system vblank and the different sources of composition (painted layers, video layers, CSS animations, WebGL, etc.)
Damage propagation is an optional WPE/GTK WebKit feature that โ when enabled โ reduces browserโs GPU utilization at the expense of increased CPU and memory utilization. Itโs very useful especially in the context of low- and mid-end
embedded devices, where GPUs are most often not too powerful and thus become a performance bottleneck in many applications.
In computer graphics, the damage term is usually used in the context of repeatable rendering and means essentially โthe region of a rendered scene that changed and requires repaintingโ.
In the context of WebKit, the above definition may be specialized a bit as WebKitโs rendering engine is about rendering web content to frames (passed further to the platform) in response to changes within a web page.
Thus the definition of WebKitโs damage refers, more specifically, to โthe region of web page view that changed since previous frame and requires repaintingโ.
On the implementation level, the damage is almost always a collection of rectangles that cover the changed region. This is exactly the case for WPE and GTK WebKit ports.
To better understand what the above means, itโs recommended to carefully examine the below screenshot of GTK MiniBrowser as it depicts the rendering of the poster circle demo
with the damage visualizer activated:
In the image above, one can see the following elements:
the web page view โ marked with a rectangle stroked to magenta color,
the damage โ marked with red rectangles,
the browser elements โ everything that lays above the rectangle stroked to a magenta color.
What the above image depicts in practice, is that during that particular frame rendering, the area highlighted red (the damage) has changed and needs to be repainted. Thus โ as expected โ only the moving parts of the demo require repainting.
Itโs also worth emphasizing that in that case, itโs also easy to see how small fraction of the web page view requires repainting. Hence one can imagine the gains from the reduced amount of painting.
Normally, the job of the rendering engine is to paint the contents of a web page view to a frame (or buffer in more general terms) and provide such rendering result to the platform on every scene rendering iteration โ
which usually is 60 times per second.
Without the damage propagation feature, the whole frame is marked as changed (the whole web page view) always. Therefore, the platform has to perform the full update of the pixels it has 60 times per second.
While in most of the use cases, the above approach is good enough, in the case of embedded devices with less powerful GPUs, this can be optimized. The basic idea is to produce the frame along with the damage information i.e. a hint for
the platform on what changed within the produced frame. With the damage provided (usually as an array of rectangles), the platform can optimize a lot of its operations as โ effectively โ it can
perform just a partial update of its internal memory. In practice, this usually means that fewer pixels require updating on the screen.
For the above optimization to work, the damage has to be calculated by the rendering engine for each frame and then propagated along with the produced frame up to its final destination. Thus the damage propagation can be summarized
as continuous damage calculation and propagation throughout the web engine.
Once the general idea has been highlighted, itโs possible to examine the damage propagation in more detail. Before reading further, however, itโs highly recommended for the reader to go carefully through the
famous โWPE Graphics architectureโ article that gives a good overview of the WebKit graphics pipeline in general and which introduces the basic terminology
used in that context.
The information on the visual changes within the web page view has to travel a very long way before it reaches the final destination. As it traverses the thread and process boundaries in an orderly manner, it can be summarized
as forming a pipeline within the broader graphics pipeline. The image below presents an overview of such damage propagation pipeline:
This pipeline starts with the changes to the web page view visual state (RenderTree) being triggered by one of many possible sources. Such sources may include:
User interactions โ e.g. moving mouse cursor around (and hence hovering elements etc.), typing text using keyboard etc.
Web API usage โ e.g. the web page changing DOM, CSS etc.
multimedia โ e.g. the media player in a playing state,
and many others.
Once the changes are induced for certain RenderObjects, their visual impact is calculated and encoded as rectangles called dirty as they
require re-painting within a GraphicsLayer the particular RenderObject
maps to. At this point, the visual changes may simply be called layer damage as the dirty rectangles are stored in the layer coordinate space and as they describe what changed within that certain layer since the last frame was rendered.
The next step in the pipeline is passing the layer damage of each GraphicsLayer
(GraphicsLayerCoordinated) to the WebKitโs compositor. This is done along with any other layer
updates and is mostly covered by the CoordinatedPlatformLayer.
The โcoordinatedโ prefix of that name is not without meaning. As threaded accelerated compositing is usually used nowadays, passing the layer damage to the WebKitโs compositor must be coordinated between the main thread and
the compositor thread.
When the layer damage of each layer is passed to the WebKitโs compositor, itโs stored in the TextureMapperLayer that corresponds to the given
layerโs CoordinatedPlatformLayer. With that โ and with all other layer-level updates โ the
WebKitโs compositor can start computing the frame damage i.e. damage that is the final damage to be passed to the very end of the pipeline.
The first step to building frame damage is to process the layer updates. Layer updates describe changes of various layer properties such as size, position, transform, opacity, background color, etc. Many of those updates
have a visual impact on the final frame, therefore a portion of frame damage must be inferred from those changes. For example, a layerโs transform change that effectively changes the layer position means that the layer
visually disappears from one place and appears in the other. Thus the frame damage has to account for both the layerโs old and new position.
Once the layer updates are processed, WebKitโs compositor has a full set of information to take the layer damage of each layer into account. Thus in the second step, WebKitโs compositor traverses the tree formed out of
TextureMapperLayer objects and collects their layer damages. Once the layer damage of a certain layer
is collected, itโs transformed from the layer coordinate space into a global coordinate space so that it can be added to the frame damage directly.
After those two steps, the frame damage is ready. At this point, it can be used for a couple of extra use cases:
for WebKitโs compositor itself to perform some extra optimizations โ as will be explained in the WebKitโs compositor optimizations section,
for layout tests.
Eventually โ regardless of extra uses โ the WebKitโs compositor composes the frame and sends it (a handle to it) to the UI Process along with frame damage using the IPC mechanism.
In the UI process, there are basically two options determining frame damage destiny โ it can be either consumed or ignored โ depending on the platform-facing implementation. At the moment of writing:
At the moment of writing, the damage propagation feature is run-time-disabled by default (PropagateDamagingInformation feature flag) and compile-time enabled by default for GTK and WPE (with new platform API) ports.
Overall, the feature works pretty well in the majority of real-world scenarios. However, there are still some uncovered code paths that lead to visual glitches. Therefore itโs fair to say the feature is still a work in progress.
The work, however, is pretty advanced. Moreover, the feature is set to a testable state and thus itโs active throughout all the layout test runs on CI.
Not only the feature is tested by every layout test that tests any kind of rendering, but it also has quite a lot of dedicated layout tests.
Not to mention the unit tests covering the Damage class.
In terms of functionalities, when the feature is enabled it:
activates the damage propagation pipeline and hence propagates the damage up to the platform,
When the feature is enabled, the main goal is to activate the damage propagation pipeline so that eventually the damage can be provided to the platform. However, in reality, a substantial part of the pipeline is always active
regardless of the features being enabled or compiled. This part of the pipeline ends before the damage reaches
CoordinatedPlatformLayer and is always active because it was used for layer-level optimizations for a long time.
More specifically โ this part of the pipeline existed long before the damage propagation feature and was using layer damage to optimize the layer painting to the intermediate surfaces.
Because of the above, when the feature is enabled, only the part of the pipeline that starts with CoordinatedPlatformLayer
is activated. It is, however, still a significant portion of the pipeline and therefore it implies additional CPU/memory costs.
When the feature is activated and the damage flows through the WebKitโs compositor, it creates a unique opportunity for the compositor to utilize that information and reduce the amount of painting/compositing it has to perform.
At the moment of writing, the GTK/WPE WebKitโs compositor is using the damage to optimize the following:
to apply global glScissor to define the smallest possible clipping rect for all the painting it does โ thus reducing the amount of painting,
to reduce the amount of painting when compositing the tiles of the layers using tiled backing stores.
Detailed descriptions of the above optimizations are well beyond the scope of this article and thus will be provided in one of the next articles on the subject of damage propagation.
As mentioned in the above sections, the feature only works in the GTK and the new-platform-API-powered WPE ports. This means that:
In the case of GTK, one can use MiniBrowser or any up-to-date GTK-WebKit-derived browser to test the feature.
In the case of WPE with the new WPE platform API the cog browser cannot be used as it uses the old API. Therefore, one has to use MiniBrowser
with the --use-wpe-platform-api argument to activate the new WPE platform API.
Moreover, as the feature is run-time-disabled by default, itโs necessary to activate it. In the case of MiniBrowser, the switch is --features=+PropagateDamagingInformation.
For quick testing, itโs highly recommended to use the latest revision of WebKit@main with wkdev SDK container and with GTK port.
Assuming one has set up the container, the commands to build and run GTKโs MiniBrowser are as follows:
Itโs also worth mentioning that WEBKIT_SHOW_DAMAGE=1 environment variable disables damage-driven GTK/WPE WebKitโs compositor optimizations and therefore some glitches that are seen without the envvar, may not be seen
when it is set. The URL to this presentation is a great example to explore various glitches that are yet to be fixed. To trigger them, itโs enough to navigate
around the presentation using top/right/down/left arrows.
This article was meant to scratch the surface of the broad, damage propagation topic. While it focused mostly on introducing basic terminology and describing the damage propagation pipeline in more detail,
it briefly mentioned or skipped completely the following aspects of the feature:
the problem of storing the damage information efficiently,
the damage-driven optimizations of the GTK/WPE WebKitโs compositor,
the most common use cases for the feature,
the benchmark results on desktop-class and embedded devices.
Therefore, in the next articles, the above topics will be examined to a larger extent.
The new WPE platform API is still not released and thus itโs not yet officially announced. Some information on it, however, is provided by
this presentation prepared for a WebKit contributors meeting.
The platform that the WebKit renders to depends on the WebKit port:
in case of GTK port, the platform is GTK so the rendering is done to GtkWidget,
in case of WPE port with new WPE platform API, the platform is one of the following:
wayland โ in that case rendering is done to the systemโs compositor,
DRM โ in that case rendering is done directly to the screen,
headless โ in that case rendering is usually done into memory buffer.
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
On the WebRTC front, basic support for Rapid Synchronization was added, along with a couple of spec coverage improvements (https://commits.webkit.org/293567@main, https://commits.webkit.org/293569@main).
Dispatch a "canceled" error event for all queued utterances in case of SpeechSynthesis.
Support for the Camera desktop portal was added recently, it will benefit mostly Flatpak apps using WebKitGTK, such as GNOME Web, for access to capture devices, which is a requirement for WebRTC support.
JavaScriptCore ๐
The built-in JavaScript/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.
Work continued on porting the in-place wasm interpreter (IPInt) to 32-bits.
We have been working on bringing the Temporal implementation in JSC up to the current spec, and a step towards that goal was implemented in WebKit PR #43849. This PR changes how calendar annotation key parsing works; it doesn't change anything observable, but sets the groundwork for parsing calendar critical flags and unknown annotations.
Releases ๐ฆ๏ธ
The recent releases of WebKitGTK and WPE WebKit 2.48 introduced a number of improvements to performance, reduced resource usage, better support for web platform features and standards, multimedia, and more!
Read more about these updates in the freshly published articles for WebKitGTK, and WPE WebKit.
Pawel Lampe published a blog post on the damage propagation feature. This feature reduces browser's GPU utilization at the expense of increased CPU and memory utilization in the WPE and GTK WebKit ports.
Our efforts to bring GstWebRTC support to WebKitGTK and WPEWebKit also include direct contributions to GStreamer. We recently improved WebRTC spec compliance in webrtcbin, by making the SDP mid attribute optional in offers and answers.
The WPE WebKit team has been working hard during the past six months and has recently released version 2.48 of the WPE port of WebKit. As is now tradition, here is an overview of the most important changes in this new stable release series.
Graphics and Rendering
The work on the graphics pipeline of WebKit continues, and a lot of improvements, refactorings, bug fixes, and optimizations have happened under the hood. These changes bring both performance and rendering improvements, and are too many to list individually. Nonetheless, there are a number of interesting changes.
GPU Worker Threads
When GPU rendering with Skia is in use, tiles will be rendered in worker threads, which has a positive impact on performance. Threads were already used when using the CPU for rendering. Note that GPU usage for rendering is not yet the default in the WPE port, but may be enabled setting WEBKIT_SKIA_ENABLE_CPU_RENDERING=0 in the environment before running programs that use WPE WebKit.
Canvas Improvements
The CanvasRenderingContext2DputImageData() and getImageData() methods have been optimized by preventing unnecessary buffer copies, resulting in improved performance and reduced memory usage.
CSS 3D Transforms
There have been several improvements handling elements that use preserve-3dCSS transforms. On top of a modest performance improvement, the changes fixed rendering issues, making the implementation compliant with the specification.
Damage Tracking
This release gained experimental support for collecting โdamageโ information, which tracks which parts of Web content produce visual changes in the displayed output. This information is then taken into account to reuse existing graphics buffers and repaint only those parts that need to be modified. This results better performance and less resource usage.
Note that this feature is disabled by default and may be previewed toggling the PropagateDamagingInformation feature flag.
GPU Process Beginnings
A new โGPU processโ is now always built, but its usage is disabled by default at runtime. This is an experimental feature that can be toggled via the UseGPUProcessForWebGL feature flag, and as the name implies at the moment this new auxiliary process only supports handling WebGL content.
The GPU process is a new addition to WebKitโs multiprocess model, in which isolated processes are responsible for different tasks: the GPU process will eventually be in charge of most tasks that make use of the graphics processing unit, in order to improve security by separating graphics handling from Web content and data access. At the same time, graphics-intensive work does not interfere with Web content handling, which may bring potential performance improvements in the future.
Multimedia
The MediaRecorder backend gained support for the WebM format and audio bitrate configuration. WebM usage requires GStreamer 1.24.9 or newer.
Video handling using the WebCodecs API no longer ignores the prefer-hardware option. It is used as a hint to attempt using hardware-accelerated GStreamer components. If that fails, software based codecs will be used as fallback.
The Web Speech API gained a new synthesis backend, using libspiel. The existing FLite-based backend is still chosen by default because the dependency is readily available in most distributions, but setting USE_SPIEL=ON at build time is recommended where libspiel may be available.
The GStreamer-GL sink can now handle DMA-BUF memory buffers, replacing the DMA-BUF sink in this way.
The WPEPlatform library is a completely new API which changes how WPE embedding API works. The aim is to make both developing WPE backends and user applications more approachable and idiomatic using GLib and GObject conventions. Inspiration has been drawn from the Cog API. A preview version is shipped along in 2.48, and as such it needs to be explicitly enabled at build time with ENABLE_WPE_PLATFORM=ON. The API may still change and applications developed using WPEPlatform are likely to need changes with future WPE WebKit releases.
Web Platform
The list of Web Platform features that are newly available in 2.48 is considerably long, and includes the following highlights:
Support for CSS progress(), media-progress() and container-progress() functionsโall part of the CSS, behind runtime flags CSSMediaProgressFunction and CSSContainerProgressFunction, respectively.
Packaging
The Web Inspector resources are no longer built into a shared library, but as a GResource bundle file. This avoids usage of the dynamic linker and allows mapping the file in memory, which brings improved resource usage.
Packagers and distributors might need some adaptation of their build infrastructure in cases where the Web Inspector resources have some ad-hoc handling. Typical cases are avoiding installation in production builds for embedded devices, or as an optional component for development builds.
For example, using the default build configuration, the file with the resources inside the installation prefix will be share/wpe-webkit-2.0/inspector.gresource, instead of the old lib/wpe-webkit-2.0/libWPEWebInspectorResources.so library.
Other Noteworthy Changes
The minimum required ICU version is now 70.1.
Reading of Remote Web Inspector protocol messages was optimized, resulting in a considerable speed-up for large messages.
The WPE WebKit team is already working on the 2.50 release, which is planned for September. In the meantime, you can expect stable updates for the 2.48 series through the usual channels.
Update on what happened in WebKit in the week from March 31 to April 7.
Cross-Port ๐ฑ
Graphics ๐ผ๏ธ
By default we divide layers that need to be painted into 512x512 tiles, and
only paint the tiles that have changed. We record each layer/tile combination
into a SkPicture and replay the painting commands in worker threads, either
on the CPU or the GPU. A change was
landed to improve the algorithm,
by recording the changed area of each layer into a single SkPicture, and for
each tile replay the same picture, but clipped to the tile dimensions and
position.
WPE WebKit ๐
WPE Platform API ๐งฉ
New, modern platform API that supersedes usage of libwpe and WPE backends.
A WPE Platform-based implementation of Media Queries' Interaction Media
Features, supporting
pointer and hover-related queries, has
landed in WPE WebKit.
When using the Wayland backend, this change exposes the current state of
pointing devices (mouse and touchscreen), dynamically reacting to changes such
as plugging or unplugging. When the new WPEPlatform API is not used, the
previous behaviour, defined at build time, is still used.
Adaptation of WPE WebKit targeting the Android operating system.
A number of fixes havebeenmerged to fix and improve building WPE WebKit for Android. This is part of an ongoing effort to make it possible to build WPE-Android using upstream WebKit without needing additional patches.
The example MiniBrowser included with WPE-Android has beenfixed to handle edge-to-edge layouts on Android 15.
From SmartTVs to light bulbs and cameras, smart devices are not hard to find in homes these days. Glancrโs smart mirror is a device that seamlessly integrates digital functionality into everyday life. Powered by its custom operating system mirr.OS, Glancr puts the Web at the forefront, allowing users to see all the information that matters to them in a customizable interface, right on a mirror. Besides being useful in smart home scenarios, Glancr can also expand the possibilities in other use cases in the industry, such as digital signage, point-of-sale devices, or even the healthcare industry.
WPE WebKit empowers mirr.OS to efficiently run and render interactive widgets and applications, ensuring a fluid and responsive user experience at the same time that enables mirr.OS to leverage the power of the Web Platform. This allows developers to create rich, web-based interfaces tailored to the smart mirrorโs unique requirements, in order to deliver a seamless and visually compelling interaction layer for users at the same time it bridges the gap between digital functionality and aesthetic appeal.
Doing a 32-bit build on ARM64 hardware now works with GCC 11.x as well.
Graphics ๐ผ๏ธ
Landed a change that improves the painting of tile fragments in the compositor if damage propagation is enabled and if the tiles sizes are bigger than 256x256. In those cases, less GPU is utilized when damage allows.
The GTK and WPE ports no longer useDisplayList to serialize the painting commands and replay them in worker threads, but SkPictureRecorder/SkPicture from Skia. Some parts of the WebCore painting system, especially font rendering, are not thread-safe yet, and our current cross-thread use of DisplayList makes it harder to improve the current architecture without breaking GTK and WPE ports. This motivated the search for an alternative implementation.
Community & Events ๐ค
Sysprof is now able to filter samples by marks. This allows for statistically relevant data on what's running when a specific mark is ongoing, and as a consequence, allows for better data analysis. You can read more here.
Update on what happened in WebKit in the week from March 17 to March 24.
Cross-Port ๐ฑ
Limited the amount data stored for certain elements of WebKitWebViewSessionState. This results in memory savings, and avoids oddly large objects which resulted in web view state being restored slowly.
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
The built-in JavaScript/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.
Fixed an integer overflow when using wasm/gc on 32-bits.
Graphics ๐ผ๏ธ
Landed a change that fixes a few scenarios where the damage was not generated on layer property changes.
Releases ๐ฆ๏ธ
WebKitGTK 2.48.0 and WPE WebKit 2.48.0 have been released. While they may not look as exciting as the 2.46 series, which introduced the use of Skia for painting, they nevertheless includes half a year of improvements. This development cycle focused on reworking internals, which brings modest performance improvements for all kinds of devices, but most importantly cleanups which will enable further improvements going forward.
For those who need longer to integrate newer releases, which we know can be a longer process for embedded device distrihytos, we have also published WPE WebKit 2.46.7 with a few stability and security fixes.
Accompanying these releases there is security advisory WSA-2025-0002 (GTK, WPE), which covers the solved security issues. Crucially, all three contain the fix for an issue known to be exploited in the wild, and therefore we strongly encourage updating.
Update on what happened in WebKit in the week from March 10 to March 17.
Cross-Port ๐ฑ
Web Platform ๐
Updated button activation behaviour and type property reflection with command and commandfor. Also aligned popovertarget behaviour with latest specification.
Update on what happened in WebKit in the week from March 3 to March 10.
Cross-Port ๐ฑ
Web Platform ๐
Forced styling to field-sizing: fixed when an input element is auto filled, and added
support for changing field-sizing
dynamically.
Fixed an issue where the imperative
popover APIs didn't take into account the source parameter for focus behavior.
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Fixed YouTube breakage on videos with
advertisements. The fix prevents scrolling to the comments section when the
videos are fullscreened, but having working video playback was considered more
important for now.
Graphics ๐ผ๏ธ
Fixed re-layout issues for form
controls with the experimental field-sizing implementation.
Landed a change that improves
the quality of damage rectangles and reduces the amount of painting done in the
compositor in some simple scenarios.
Introduce a hybrid threaded rendering
mode, scheduling tasks to both the CPU and GPU worker pools. By default we use
CPU-affine rendering on WPE, and GPU-affine rendering on the GTK port,
saturating the CPU/GPU worker pool first, before switching to the GPU/CPU.
Infrastructure ๐๏ธ
We have recently enabled automatic nightly runs of WPT tests with WPE for the
Web Platform Tests (WPT) dashboard. If you click on the โEditโ button at the
wpt.fyi dashboard now there is the option to select WPE.
These nightly runs happen now daily on the TaskCluster CI sponsored by Mozilla
(Thanks to James Graham!).
If you want to run WPT tests with WPE WebKit locally, there are instructions
at the WPT documentation.
After fixing
an issue with Trusted Types when doing attribute mutation within the default
callback, and implementing
performance improvements for Trusted Types enforcement, the
Trusted Types
implementation is now considered stable and has been
enabled by default.
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Landed one fix which,
along with previous patches, solved the webKitMediaSrcStreamFlush() crash
reported in bug #260455.
Unfortunately, in some pages where the crash previously occurred, now a
different blank video bug has been revealed. The cause of this bug is known,
but fixing it would cause performance regressions in pages with many video
elements. Work is ongoing to find a better solution for both.
The initial support of MP4-muxed WebVTT in-band text
tracks is about to be merged,
which will bring this MSE feature to the ports using GStreamer. Text tracks
for the macOS port of WebKit only landed two weeks
ago and we expect there will be
issues to iron out in WebKit ports, multiplatform code and even potentially in
spec workโwe are already aware of a few potential ones.
Note that out-of band text-tracks are well supported in MSE across browsers
and commonly used. On the other hand, no browsers currently ship with in-band
text track support in MSE at this point.
Support for MediaStreamTrack.configurationchange events was
added,
along with related
improvements
in the GStreamer PipeWire plugin. This will allow WebRTC applications to
seamlessly handle default audio/video capture changes.
Graphics ๐ผ๏ธ
Continued improving the support for handling graphics damage:
Added support
for validating damage rectangles in Layout Tests.
Landed a change that adds
layout tests covering the damage propagation feature.
Landed a change that fixes
damage rectangles on layer resize operations.
Landed a change that
improves damage rectangles produced by scrolling so that they are
clipped to the parent container.
The number of threads used for painting with the GPU has been slightly
tweaked, which brings a measurable
performance improvement in all kinds of devices with four or mores processor
cores.
Releases ๐ฆ๏ธ
The stable branch
for the upcoming 2.48.x stable release series of the GTK and WPE ports has
been created. The first preview releases from this branch are WebKitGTK
2.47.90 and
WPE WebKit 2.47.90.
People willing to report issues and help with stabilization are encouraged to
test them and report issues in Bugzilla.
Community & Events ๐ค
Published a blog
post
that presents an opinionated approach to the work with textual logs obtained
from WebKit and GStreamer.
WebKit has grown into a massive codebase throughout the years. To make developersโ lives easier, it offers various subsystems and integrations.
One such subsystem is a logging subsystem that offers the recording of textual logs describing an execution of the internal engine parts.
The logging subsystem in WebKit (as in any computer system), is usually used for both debugging and educational purposes. As WebKit is a widely-used piece of software that runs on
everything ranging from desktop-class devices up to low-end embedded devices, itโs not uncommon that logging is sometimes the only way for debugging when various limiting
factors come into play. Such limiting factors donโt have to be only technical - it may also be that the software runs on some restricted systems and direct debugging is not allowed.
Requirements for efficient work with textual logs #
Regardless of the reasons why logging is used, once the set of logs is produced, one can work with it according to the particular need.
From my experience, efficient work with textual logs requires a tool with the following capabilities:
Ability to search for a particular substring or regular expression.
Ability to filter text lines according to the substring or regular expressions.
Ability to highlight particular substrings.
Ability to mark certain lines for separate examination (with extra notes if possible).
Ability to save and restore the current state of work.
While all text editors should be able to provide requirement 1, requirements 2-5 are usually more tricky and text editors wonโt support them out of the box.
Fortunately, any modern extensible text editor should be able to support requirements 2-5 after some extra configuration.
Throughout the following sections, I use Emacs, the classic โextensible, customizable, free/libre text editorโ, to showcase how it can be set up and used to meet
the above criteria and to make work with logs a gentle experience.
Emacs, just like any other text editor, provides the support for requirement 1 from the previous section out of the box.
To support requirement 2, it requires some extra mode. My recommendation for that is loccur - the minor mode
that acts just like a classic grep *nix utility yet directly in the editor. The benefit of that mode (over e.g. occur)
is that it works in-place. Therefore itโs very ergonomic and - as Iโll show later - it works well in conjunction with bookmarking mode.
Installation of loccur is very simple and can be done from within the built-in package manager:
M-x package-install RET loccur RET
With loccur installed, one can immediately start using it by calling M-x loccur RET <regex> RET. The figure below depicts the example of filtering:
highlight-symbol - the package with utility functions for text highlighting #
To support requirement 3, Emacs also requires the installation of extra module. In that case my recommendation is highlight-symbol
that is a simple set of functions that enables basic text fragment highlighting on the fly.
Installation of this module is also very simple and boils down to:
M-x package-install RET highlight-symbol RET
With the above, itโs very easy to get results like in the figure below:
just by moving the cursor around and using C-c h to toggle the highlight of the text at the current cursor position.
bm - the package with utility functions for buffer lines bookmarking #
Finally, to support requirements 4 and 5, Emacs requires one last extra package. This time my recommendation is bm
that is quite a powerful set of utilities for text bookmarking.
In this case, installation is also very simple and is all about:
M-x package-install RET bm RET
In a nutshell, the bm package brings some visual capabilities like in the figure below:
as well as non-visual capabilities that will be discussed in further sections.
Once all the necessary modules are installed, itโs worth to spend some time on configuration. With just a few simple tweaks itโs possible to make the work with logs
simple and easily reproducible.
To not influence other workflows, I recommend attaching as much configuration as possible to any major mode and setting that mode as a default for
files with certain extensions. The configuration below uses a major mode called text-mode as the one for working with logs and associates all the files with a
suffix .log with it. Moreover, the most critical commands of the modes installed in the previous sections are binded to the key shortcuts. The one last
thing is to enable truncating the lines ((set-default 'truncate-lines t)) and highlighting the line that the cursor is currently at ((hl-line-mode 1)).
To show what the workflow of Emacs is with the above configuration and modules, some logs are required first. Itโs very easy to
get some logs out of WebKit, so Iโll additionally get some GStreamer logs as well. For that, Iโll build a WebKit GTK port from the latest revision of WebKit repository.
To make the build process easier, Iโll use the WebKit container SDK.
The above command disables the ENABLE_JOURNALD_LOG build option so that logs are printed to stderr. This will result in the WebKit and GStreamer logs being bundled together as intended.
Once the build is ready, one can run any URL to get the logs. Iโve chosen a YouTube conformance tests suite from 2021 and selected test case โ39. PlaybackRateChangeโ
to get some interesting entries from multimedia-related subsystems:
Once the logs are collected, one can open them using Emacs and start making sense out of them by gradually exploring the flow of execution. In the below exercise, I intend to understand
what happened from the multimedia perspective during the execution of the test case โ39. PlaybackRateChangeโ.
The first step is usually to find the most critical lines that mark more/less the area in the file where the interesting things happen. In that case I propose using M-x loccur RET CONSOLE LOG RET to check what the
console logs printed by the application itself are. Once some lines are filtered, one can use bm-toggle command (C-c t) to mark some lines for later examination (highlighted as orange):
For practicing purposes I propose exiting the filtered view M-x loccur RET and trying again to see what events the browser was dispatching e.g. using M-x loccur RET on node node 0x7535d70700b0 VIDEO RET:
In general, the combination of loccur and substring/regexp searches should be very convenient to quickly explore various types of logs along with marking them for later. In case of very important log
lines, one can additionally use bm-bookmark-annotate command to add extra notes for later.
Once some interesting log lines are marked, the most basic thing to do is to jump between them using bm-previous (C-c n) and bm-next (C-c p). However, the true power of bm mode comes with
the use of M-x bm-show RET to get the view containing only the lines marked with bm-toggle (originally highlighted orange):
This view is especially useful as it shows only the lines deliberately marked using bm-toggle and allows one to quickly jump to them in the original file. Moreover, the lines are displayed in
the order they appear in the original file. Therefore itโs very easy to see the unified flow of the system and start making sense out of the data presented. Whatโs even more interesting,
the view contains also the line numbers from the original file as well as manually added annotations if any. The line numbers are especially useful as they may be used for resuming the work
after ending the Emacs session - which Iโll describe further in this section.
When the *bm-bookmarks* view is rendered, the only problem left is that the lines are hard to read as they are displayed using a single color. To overcome that problem one can use the macros from
the highlight-symbol package using the C-c h shortcut defined in the configuration. The result of highlighting some strings is depicted in the figure below:
With some colors added, itโs much easier to read the logs and focus on essential parts.
On some rare occasions it may happen that itโs necessary to close the Emacs session yet the work with certain log file is not done and needs to be resumed later. For that, the simple trick is to open the current
set of bookmarks with M-x bm-show RET and then save that buffer to the file. Personally, I just create a file with the same name as log file yet with .bm prefix - so for log.log itโs log.log.bm.
Once the session is resumed, it is enough to open both log.log and log.log.bm files side by side and create a simple ad-hoc macro to use line numbers from log.log.bm to mark them again in the log.log
file:
As shown in the above gif, within a few seconds all the marks are applied in the buffer with log.log file and the work can resume from that point i.e. one can jump around using bm, add new marks etc.
Although the above approach may not be ideal for everybody, I find it fairly ergonomic, smooth, and covering all the requirements I identified earlier.
Iโm certain that editors other than Emacs can be set up to allow the same or very similar flow, yet any particular configurations are left for the reader to explore.
Igalia is arranging the twelfth annual Web Engines Hackfest, which will be held on Monday 2nd June through Wednesday 4th June.
As usual, this is a hybrid event, at Palexco in A Coruรฑa (Galicia, Spain) as well as remotely.
Registration is now open:
Submit your talks and breakout sessions. The deadline to submit proposals is Wednesday 30th April.
The Web Engines Hackfest is an event where folks working on various parts of the web platform gather for a few days to share knowledge and discuss a variety of topics.
These topics include web standards, browser engines, JavaScript engines, and all the related technology around them.
Last year, we had eight talks (watch them on YouTube) and 15 breakout sessions (read them on GitHub).
A wide range of experts with a diverse set of profiles and skills attend each year, so if you are working on the web platform, this event is a great opportunity to chat with people that are both developing the standards and working on the implementations.
Weโre really grateful for all the people that regularly join us for this event; you are the ones that make this event something useful and interesting for everyone! ๐
Really enjoying Web Engines Hackfest by @igalia once again. Recommended for everyone interested in web technology.
The breakout sessions are probably the most interesting part of the event.
Many different topics are discussed there, from high-level issues like how to build a new feature for the web platform, to lower-level efforts like the new WebKit SDK container.
Together with the hallway discussions and impromptu meetings, the Web Engines Hackfest is an invaluable experience.
Big shout-out to Igalia for organising the Web Engines Hackfest every year since 2014, as well as the original WebKitGTK+ Hackfest starting in 2009.
The event has grown and weโre now close to 100 onsite participants with representation from all major browser vendors.
If your organization is interested in helping make this event possible, please contact us regarding our sponsorship options.
The GStreamer video frame converter, used to show video frames in the canvas or
WebGL, has been fixed to use the right GL context and now supports DMA-BUF
video frames, too.
Added support to the eotf
additional MIME type parameter when checking for supported multimedia content
types. This is required by some streaming sites like YouTube TV.
The WebKit ports that use CMake as their build systemโas is the case for the GTK and WPE onesโnow enable C++ library assertions by default, when building against GNU libstdc++ or LLVM's libc++. This adds lightweight runtime checks to a number of C++ library facilities, mostly aimed at detecting out-of-bounds memory access, and does not have a measurable performance impact on typical browsing workloads.
A number of Linux distributions were already enabling these assertions as part of their security hardening efforts (e.g. Fedora or Gentoo) and they do help finding actual bugs. As a matter of fact, a number of issues were fixed before all the WebKit API and layout tests with the assertions enabled and the patch could be merged! Going forward, this will prevent accidentally introducing bugs new due to wrong usage of the C++ standard library.
Update on what happened in WebKit in the week from February 3 to February 11.
Cross-Port ๐ฑ
Fixed an assertion crash in the
remote Web Inspector when its resources contain an UTF-8 โnon-breaking spaceโ
character.
Multimedia ๐ฅ
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Media playback now supports choosing the output audio device on a per element basis, using the setSinkId() API. This also added the support needed for enumerating audio outputs, which is needed by Web applications to obtain the identifiers of the available devices. Typical usage includes allowing the user to choose the audio output used in WebRTC-based conference calls.
For now feature flags ExposeSpeakers, ExposeSpeakersWithoutMicrophone, and PerElementSpeakerSelection need to be enabled for testing.
Landed a change that adds a
visualization for damage rectangles, controlled by the WEBKIT_SHOW_DAMAGE
environment variable. This highlights areas damaged during rendering of every
frameโas long as damage propagation is enabled.
Releases ๐ฆ๏ธ
Stable releases of WebKitGTK 2.46.6 and WPE WebKit 2.46.6 are now available. These come along with the first security advisory of the year (WSA-2025-0001: GTK, WPE): they contain mainly security fixes, and everybody is advised to update.
The unstable release train continues as well, with WebKitGTK 2.47.4 and WPE WebKit 2.47.4 available for testing. These are snapshots of the current development status, and while expected to work there may be rough edgesโif you encounter any issue, reports at the WebKit Bugzilla are always welcome.
The recently released libwpe 1.16.1 accidentally introduced an ABI break, which has been corrected in libwpe 1.16.2. There are no other changes, and the latter should be preferred.
This blog post is to announce that Igalia has gotten a grant from NLnet Foundation to work on solving cross-root ARIA issues in Shadow DOM. My colleague Alice Boxhall, which has been working on sorting out this issue since several years ago, together with support form other igalians is doing the work related to this grant.
Briefly speaking, there are mainly two different problems when you want to reference elements for ARIA attributes cross shadow root boundaries.
First issue is that you cannot reference things outside the Shadow DOM. Imagine you have a custom element (#customButton) which contains a native button in its Shadow DOM, and you want to associate the internal button with a label (#label) which is outside in the light DOM.
And the second problem is that you cannot reference things inside a Shadow DOM from the outside. Imagine the opposite situation where you have a custom label (#customLabel) with a native label in its Shadow DOM that you want to reference from a button (#button) in the light DOM.
This is a huge issue for web components because they cannot use Shadow DOM, as they would like due to its encapsulation properties, if they want to provide an accessible experience to users. For that reason many of the web components libraries donโt use yet Shadow DOM and have to rely on workarounds or custom polyfills.
The Accessibility Object Model (AOM) effort was started several years ago aiming to solve several issues including the one described before, that had a wider scope and tried to solve many different things including the problems described in this blog post. At that time Alice was at Google and Alex Surkov at Mozilla, both were part of this effort. Coincidentally, they are now at Igalia, which together with Joanmarie Diggs and Valerie Young create a dream team of accessibility experts in our company.
Even when the full problem hasnโt been sorted out yet, there has been some progress with the Element Reflection feature which allows ARIA relationship attributes to be reflected as element references. Whit this users can specify them without the need to assign globally unique ID attributes to each element. This feature has been implemented in Chromium and WebKit by Igalia. So instead of doing something like:
<buttonid="button"aria-describedby="description">Button</button> <divid="description">Description of the button.</div>
You could specify it like:
<buttonid="button">Button</button> <divid="description">Description of the button.</div> <script> button.ariaDescribedByElements =[description]; </script>
Coming back to Shadow DOM, this feature also enables authors to specify ARIA relationships pointing to things outside the Shadow DOM (the first kind of problem described in the previous section), however it doesnโt allow to reference elements inside another Shadow DOM (the second problem). Anyway letโs see an example of how this will solve the first issue:
const button = document.createElement("button"); button.textContent ="Button"; /* Here is where we reference the outer label from the button inside the Shadow DOM. */ button.ariaLabelledByElements =[label]; shadowRoot.appendChild(button);
const bar = document.createElement("div"); bar.textContent ="bar"; shadowRoot.appendChild(bar); </script>
Apart from Element Reflection, which only solves part of the issues, there have been other ideas about how to solve these problems. Initially Cross-root ARIA Delegation proposal by Leo Balter at Salesforce. A different one called Cross-root ARIA Reflection by Westbrook Johnson at Adobe. And finally the Reference Target for Cross-root ARIA proposal by Ben Howell at Microsoft.
Again if you want to learn more about the different nuances of the previous proposals you can revisit Aliceโs blog post.
At this point this is the most promising proposal is the Reference Target one. This proposal allows the web authors to use Shadow DOM and still donโt break the accessibility of their web applications. The proposal is still in flux and itโs currently being prototyped in Chromium and WebKit. Anyway as an example this is the kind of API shape that would solve the second problem described in the initial section, where we reference a label (#actualLabel) inside the Shadow DOM from a button (#button) in the light DOM.
As part of this grant weโll work on all the process to get the Reference Target proposal ready to be shipped in the web rendering engines. Some of the tasks that will be done during this project include work in different fronts:
Proposal: Help with the work on the proposal identifying issues, missing bits, design solutions, providing improvements, keeping it up to date as the project evolves.
Specification: Write the specification text, discuss and review it with the appropriate working groups, improved it based on gathered feedback and implementation experience, resolve issues identified in the standards bodies.
Implementation: Prototype implementation in WebKit to verify the proposal, upstream changes to WebKit, fix bugs on the implementation, adapt it to spec modifications.
Testing: Analyze current WPT tests, add new ones to increase coverage, validate implementations, keep them up-to-date as things evolve.
Outreach: Blog posts explaining the evolution of the project and participation in events with other standards folks to have the proper discussions to move the proposal and specification forward.
Weโre really grateful that NLnet has trusted us to this project, and we really hope this will allow to fix an outstanding accessibility issue in the web platform that has been around for too many time already. At the same point itโs a bit sad, that the European Union through the NGI funds is the one sponsoring this project, when it will have a very important impact for several big fishes that are part of the Web Components WG.
If you want to follow the evolution of this project, Iโd suggest you to follow Aliceโs blog where sheโll be updating us about the progress of the different tasks.
Update on what happened in WebKit in the week from January 27 to February 3.
Cross-Port ๐ฑ
The documentation now has a section on how to use the Web Inspector
remotely. This makes information on
this topic easier to find, as it was previously scattered around a few
different locations.
Jamie continues her Coding Experience work around bringing WebExtensions to the
WebKitGTK port. A good part of this involves porting
functionality
from Objective-C, which only the Apple WebKit ports would use, into C++ code
that all ports may use. The latest in this saga was
WebExtensionStorageSQLiteStore.
Web Platform ๐
The experimental support for Invoker
Commands
has been updated to match latest
spec changes.
GStreamer-based multimedia support for WebKit, including (but not limited to)
playback, capture, WebAudio, WebCodecs, and WebRTC.
The GStreamer WebRTC backend can now recycle inactive
senders
and support for inactive receivers was also improved. With these changes,
support for screen sharing over WebRTC is now more reliable.
Nushell is a new shell (get it?) in development since 2019. Where other shells like bash and zsh treat all data as raw text,
nu instead provides a type system for all data flowing through its pipelines, with many commands inspired by functional languages to manipulate
that data. The examples on their homepage and in the README.md demonstrate this well,
and I recommend taking a quick look if youโre not familiar with the language.
I have been getting familiar with Nu for a few months now, and found it a lot more approachable and user-friendly than traditional shells,
and particularly helpful for exploring logs.
I wonโt go over all the commands I use in detail, so if anything is ever unclear, have a look at the Command Reference.
The most relevant categories for our use case are probably Strings and Filters.
From inside nushell, you can also use help some_cmd or some_cmd --help, or help commands for a full table of commands that can be manipulated and searched like
any other table in nu. And for debugging a pipeline, describe is a very useful command that describes the type of its input.
First of all, we need some custom commands to parse the raw logs into a nu table. Luckily, nushell provides a parse command for exacly this use case,
and we can define this regex to use with it:
(I use a simple pipeline here to split the string over multiple lines for better readability, it just concatenates the list elements.)
Lets run a simple pipeline to get some logs to play around with: GST_DEBUG=*:DEBUG GST_DEBUG_FILE=sample.log gst-launch-1.0 videotestsrc ! videoconvert ! autovideosink
For parsing the file, we need to be careful to remove any ansi escapes, and split the input into lines. On top of that, we will also store the result to a variable for ease of use: let gst_log = open sample.log | ansi strip | lines | parse --regex $gst_regex
You can also define a custom command for this, which would look something like:
Define it directly on the command line, or place it in your configuration files. Either way, use the command like this: let gst_log = open sample.log | from gst logs
Some basic commands for working with the parsed data #
If you take a look at a few lines of the table, it should look something like this: $gst_log | skip 10 | take 10
skip and take do exactly what it says on the tin - removing the first N rows, and showing only the first N rows, respectively. I use them here to keep the examples short.
To ignore columns, use reject: $gst_log | skip 10 | take 5 | reject time pid thread
Meanwhile, get returns a single column as a list, which can for example be used with uniq to get a list of all objects in the log: $gst_log | get object | uniq | take 5
Filtering rows by different criteria works really well with where. $gst_log | where thread in ['0x7f467c000b90' '0x232fefa0'] and category == GST_STATES | take 5
And if you need to merge multiple logs, I recommend using sort-by time. This could look like let gst_log = (open sample.log) + (open other.log) | from gst logs | sort-by time
While there are many other useful commands, there is one more command I find incredbly useful: explore.
It is essentially the nushell equivalent to less, and while it is still quite rough around the edges,
Iโve been using it all the time, mostly for its interactive REPL.
First, just pipe the parsed log into explore: $gst_log | explore
Now, using the :try command opens its REPL. Enter any pipeline at the top, and you will be able to explore its output below:
Switch between the command line and the pager using Tab, and while focused on the pager, search forwards or backwards using / and ?, or enter :help for explanations.
Also have a look at the documentation on explore in the Nushell Book.
GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.
Fixed the assertion error "pipeline and player states are not synchronized" related to muted video playback in the presence of scroll. Work is ongoing regarding other bugs reproduced with the same video, some of them related to scroll and some likely indepedent.
Fixed lost initial audio
samples played using WebAudio on
32-bit Raspberry Pi devices, by preventing the OpenMAX subsystem to enter
standby mode.
Graphics ๐ผ๏ธ
Landed a change that fixes damage propagation of 3D-transformed layers.
Fixed a regression visiting any web page making use of accelerated ImageBuffers (e.g. canvas) when CPU rendering is used. We were unconditionally creating OpenGL fences, even in CPU rendering mode, and tried to wait for completion in a worker thread, that had no OpenGL context (due to CPU rendering). This is an illegal operation in EGL and fired an assertion, crashing the WebProcess.
Releases ๐ฆ๏ธ
Despite the work on the WPE Platform API, we continue to maintain the โclassicโ stack based on libwpe. Thus, we have released libwpe 1.16.1 with the smallโbut importantโaddition of support for representing analog button inputs for devices capable of reporting varying amounts of pressure.