<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">

<channel>
	<title>Planet Igalia WebKit</title>
	<link>https://planet.igalia.com/webkit</link>
	<language>en</language>
	<description>Planet Igalia WebKit - https://planet.igalia.com/webkit</description>

<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #77</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-77/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-77/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from September 7 to September 14.&lt;/p&gt;
&lt;p&gt;
In this week's edition, the PNG image decoder received a much
needed cleanup, as well as another swipe of unassorted graphics
improvements, most notably in the Layer-Based SVG Engine. Finally,
we also have an exciting and informative article about how to use
the WPE Platform API on Raspberry Pi.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320960@main&quot;&gt;Cleaned up the PNG image decoder&lt;/a&gt; a little bit, by removing conditional code that was used to support &lt;code&gt;libpng&lt;/code&gt; versions older than 1.5.0, and requiring that as the minimum version. Given that version 1.5.0 was released back in 2011, it is expected that every system where current WebKit works will have much newer versions of &lt;code&gt;libpng&lt;/code&gt; anyway.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320988@main&quot;&gt;Fixed an assertion failure&lt;/a&gt; for an outermost &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; with non-visible &lt;code&gt;overflow&lt;/code&gt; in the Layer-Based SVG Engine (LBSE) by refreshing its scroll dimensions at the end of layout, a first step towards reworking &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; scrolling, which is not yet spec compliant.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320797@main&quot;&gt;Fixed an assertion failure&lt;/a&gt; when computing filter outsets for &lt;code&gt;&amp;lt;feGaussianBlur&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;feDropShadow&amp;gt;&lt;/code&gt; with a negative &lt;code&gt;stdDeviation&lt;/code&gt;, which turns the primitive off but was still passed on to the outset calculation, affecting both SVG filters and CSS reference filters.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320622@main&quot;&gt;Stopped reporting damage every frame&lt;/a&gt; for composited layers that use CSS &lt;code&gt;filter&lt;/code&gt; in the Skia based compositor, so a blurred or drop-shadowed element is now only repainted when its subtree, or the applied (possibly animated) filter value, actually changed.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320634@main&quot;&gt;Fixed&lt;/a&gt; the bug that composited layers with clipping or masking and fully covered by opaque child layers were treated as opaque layers.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Fixed two debug assertion failures in the Layer-Based SVG Engine (LBSE), one where an SVG &lt;code&gt;transform&lt;/code&gt; change &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320722@main&quot;&gt;left ancestor layer repaint rects stale&lt;/a&gt; and one where &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320757@main&quot;&gt;repainting on a compositing change during layout&lt;/a&gt; tripped an over-strict check on the paint offset cache.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320811@main&quot;&gt;Fixed&lt;/a&gt; the white noised image issue on the combination of i915 driver and Intel Arc after &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/308458@main&quot;&gt;308458@main&lt;/a&gt; introduced image atlas uploading.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;community-events-handshake&quot;&gt;Community &amp;amp; Events &#129309;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Published a &lt;a rel=&quot;external&quot; href=&quot;https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/&quot;&gt;blog post&lt;/a&gt; describing the steps to try WPE Platform API on Raspberry Pi with latest WebKit &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 14 Sep 2026 19:07:43 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Hironori Fujii: Asynchronous scrolling for touch events in WPE and WebKitGTK</title>
	<guid>https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/</guid>
	<link>https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/</link>
	<description>
&lt;ul&gt;
&lt;li&gt;Bug: &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=318938&quot;&gt;318938 &#8211; Support touch event asynchronous scrolling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Commit: &lt;a href=&quot;https://commits.webkit.org/319347@main&quot;&gt;319347@main&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The WPE and GTK ports have supported touch events for a long time, but
asynchronous scrolling only worked for wheel events. Scrolling driven by touch
still depended on the web process main thread. This change puts touch events on
the asynchronous scrolling path too.&lt;/p&gt;
&lt;p&gt;Let&#8217;s start with the background: what asynchronous scrolling is and why it needs
to be built differently here.&lt;/p&gt;
&lt;h2 id=&quot;what-is-asynchronous-scrolling&quot; tabindex=&quot;-1&quot;&gt;What is asynchronous scrolling? &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;why-it-is-needed&quot; tabindex=&quot;-1&quot;&gt;Why it is needed &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A naive implementation of scrolling looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The UI process receives an input event (wheel or touch).&lt;/li&gt;
&lt;li&gt;It sends the event to the web process main thread.&lt;/li&gt;
&lt;li&gt;The main thread runs the page&#8217;s JavaScript event listeners.&lt;/li&gt;
&lt;li&gt;If nothing called &lt;code&gt;preventDefault()&lt;/code&gt;, the scroll position is updated.&lt;/li&gt;
&lt;li&gt;The page is rendered at the new scroll position.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Step 3 is the problem. The main thread is easily blocked for hundreds of
milliseconds by JavaScript execution or layout, and scrolling is frozen for that
whole time. Your finger moves, the screen does not. That is what synchronous
scrolling feels like.&lt;/p&gt;
&lt;p&gt;Asynchronous scrolling moves the work off the main thread: the &lt;strong&gt;scrolling
thread&lt;/strong&gt; updates the scroll position, and the &lt;strong&gt;compositor thread&lt;/strong&gt; composites
and presents the frame. Neither needs the main thread, so scrolling keeps running
at 60fps even when the main thread is busy.&lt;/p&gt;
&lt;h3 id=&quot;the-scrolling-tree-and-event-regions&quot; tabindex=&quot;-1&quot;&gt;The scrolling tree and event regions &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Two data structures make this possible.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;scrolling tree&lt;/strong&gt; is a tree of the scrollable areas of a page. The main
frame, &lt;code&gt;overflow: scroll&lt;/code&gt; elements, &lt;code&gt;position: fixed&lt;/code&gt;/&lt;code&gt;sticky&lt;/code&gt; elements and so on
each become a node holding its own scroll position and a reference to its layer.
The scrolling thread updates scroll positions by looking only at this tree, and
the compositor thread then draws the layers at their new positions &#8212; the main
thread is not involved in either step.&lt;/p&gt;
&lt;p&gt;But there are places where scrolling on its own would be wrong, because the page
might call &lt;code&gt;preventDefault()&lt;/code&gt; from an &lt;code&gt;addEventListener(&amp;quot;touchstart&amp;quot;, ...)&lt;/code&gt;
handler. That is what &lt;strong&gt;event regions&lt;/strong&gt; are for.&lt;/p&gt;
&lt;p&gt;An event region records, per layer and at rendering time, &#8220;this rectangle has a
listener for this kind of event&#8221;. &lt;code&gt;EventRegion&lt;/code&gt; keeps separate regions for
&lt;code&gt;touchstart&lt;/code&gt;, &lt;code&gt;touchmove&lt;/code&gt;, &lt;code&gt;pointerdown&lt;/code&gt;, &lt;code&gt;mousedown&lt;/code&gt; and friends, and for any
given point it yields a &lt;code&gt;TrackingType&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TrackingType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token base-clause&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    NotTracking &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// No listener. The event does not even need to be delivered.&lt;/span&gt;&lt;br /&gt;    Asynchronous &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Passive listeners only. Scroll now, notify the page later.&lt;/span&gt;&lt;br /&gt;    Synchronous &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// A non-passive listener may call preventDefault(). We must wait.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The passive distinction is what makes &lt;code&gt;Asynchronous&lt;/code&gt; possible.
&lt;code&gt;preventDefault()&lt;/code&gt; cancels an event only if the listener was registered with
&lt;code&gt;passive: false&lt;/code&gt;; from a passive listener it does nothing. And on &lt;code&gt;window&lt;/code&gt;,
&lt;code&gt;document&lt;/code&gt; and &lt;code&gt;document.body&lt;/code&gt;, &lt;code&gt;touchstart&lt;/code&gt;/&lt;code&gt;touchmove&lt;/code&gt; (and &lt;code&gt;wheel&lt;/code&gt;) default to
&lt;code&gt;passive: true&lt;/code&gt; &#8212; see
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners&quot;&gt;MDN: Using passive listeners&lt;/a&gt;.
So &lt;code&gt;Asynchronous&lt;/code&gt; is the case &#8220;there are listeners, but none of them can cancel
the scroll&#8221;: start scrolling now, deliver the event to the main thread
afterwards.&lt;/p&gt;
&lt;p&gt;Because this information travels to the scrolling thread along with the layer
tree, an incoming input event can be classified without waking the main thread.
That is the heart of asynchronous scrolling.&lt;/p&gt;
&lt;h3 id=&quot;why-the-ios-implementation-could-not-be-reused&quot; tabindex=&quot;-1&quot;&gt;Why the iOS implementation could not be reused &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The iOS port already implements asynchronous scrolling for touch events, but it
could not be reused, because the process layout is different.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iOS:
  UI process:  platform layer tree + scrolling tree + touch event input
  Web process: main thread (DOM, layout)

WPE / GTK (Coordinated Graphics):
  UI process:  touch event input only
  Web process: main thread (DOM, layout)
               + EventDispatcher thread / scrolling thread
               + platform layer tree + scrolling tree
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On iOS both the platform layer tree and the scrolling tree live in the UI
process &#8212; the very process that receives touch events &#8212; so the classification
and the scroll both happen right there. On WPE and GTK we use Coordinated
Graphics, and both trees live in the web process instead. The classification
therefore has to happen &lt;em&gt;after&lt;/em&gt; sending the event to the web process, but
&lt;em&gt;before&lt;/em&gt; touching the main thread.&lt;/p&gt;
&lt;p&gt;Fortunately the same problem was already solved for wheel events. The web
process has an &lt;strong&gt;EventDispatcher thread&lt;/strong&gt; that receives wheel events from the UI
process without going through the main thread and consults the scrolling tree
directly. This change builds the same shape for touch events.&lt;/p&gt;
&lt;h3 id=&quot;how-a-touch-becomes-a-scroll-in-wpe&quot; tabindex=&quot;-1&quot;&gt;How a touch becomes a scroll in WPE &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One more piece of background: in WPE a touch does not scroll the page directly.
Touch events are first offered to the page; only if the page does not consume
them does the UI process turn the touch sequence into scrolling.&lt;/p&gt;
&lt;p&gt;The decision point is &lt;code&gt;PageClientImpl::doneWithTouchEvent()&lt;/code&gt;. If the page handled
the event, gesture detection is cancelled with
&lt;code&gt;wpe_gesture_controller_cancel()&lt;/code&gt; so the engine does not also act on it. If it
was not handled, the event is fed to the WPE platform gesture controller via
&lt;code&gt;ViewPlatform::handleGesture()&lt;/code&gt;, and a recognized &lt;code&gt;WPE_GESTURE_DRAG&lt;/code&gt; is turned
into a synthetic scroll event pushed back into the page as a wheel event:&lt;/p&gt;
&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;GRefPtr&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;WPEEvent&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; simulatedScrollEvent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;adoptGRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wpe_event_scroll_new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    m_wpeView&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WPE_INPUT_SOURCE_TOUCHSCREEN&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;WPEModifiers&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TRUE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleNativeWheelEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WebKit&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;NativeWebWheelEvent&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;simulatedScrollEvent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; phase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;TRUE&lt;/code&gt; is &lt;code&gt;precise_deltas&lt;/code&gt;: touch-driven scrolling in WPE reaches the engine
as precise-delta wheel events, which becomes relevant later.&lt;/p&gt;
&lt;p&gt;The important consequence is this: &lt;strong&gt;the UI process cannot start scrolling until
it knows whether the page is going to consume the touch.&lt;/strong&gt; That answer used to
come from the web process main thread &#8212; so when the main thread was busy,
scrolling did not start. That is the problem this change fixes.&lt;/p&gt;
&lt;h2 id=&quot;the-change&quot; tabindex=&quot;-1&quot;&gt;The change &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;enabling-touch-event-regions&quot; tabindex=&quot;-1&quot;&gt;Enabling touch event regions &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A new &lt;code&gt;ENABLE(COORDINATED_TOUCH_EVENTS)&lt;/code&gt; is introduced in &lt;code&gt;PlatformEnableGlib.h&lt;/code&gt;,
and it turns on &lt;code&gt;ENABLE(TOUCH_EVENT_REGIONS)&lt;/code&gt; whenever touch events are enabled
on WPE/GTK. The &lt;code&gt;AlwaysUseTouchEventRegions&lt;/code&gt; preference now defaults to &lt;code&gt;true&lt;/code&gt;
under that flag, so &lt;code&gt;Document::shouldUseTouchEventRegions()&lt;/code&gt; returns true and
touch regions are actually recorded on the layers during rendering.&lt;/p&gt;
&lt;h3 id=&quot;ui-process-send-to-the-eventdispatcher-instead-of-the-main-thread&quot; tabindex=&quot;-1&quot;&gt;UI process: send to the EventDispatcher instead of the main thread &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The old &lt;code&gt;WebPageProxy::handleTouchEvent()&lt;/code&gt; consulted a &lt;code&gt;touchEventTracking&lt;/code&gt; state
kept in the UI process and sent &lt;code&gt;Messages::WebPage::TouchEvent&lt;/code&gt;, i.e. straight to
the web process main thread.&lt;/p&gt;
&lt;p&gt;The new version delegates all classification to the web process and only queues
events and delivers answers. One event is in flight at a time; the next is sent
when the reply arrives. The flood of &lt;code&gt;touchmove&lt;/code&gt; events produced while a finger
moves is coalesced into the newest queued event when that is also a &lt;code&gt;touchmove&lt;/code&gt;,
and the coalesced events are flushed to &lt;code&gt;doneWithTouchEvent()&lt;/code&gt; together with the
reply.&lt;/p&gt;
&lt;p&gt;The destination is now &lt;code&gt;Messages::EventDispatcher::TouchEvent&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;web-process-classification-on-the-eventdispatcher-thread&quot; tabindex=&quot;-1&quot;&gt;Web process: classification on the EventDispatcher thread &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;EventDispatcher::touchEvent()&lt;/code&gt; runs on the &lt;code&gt;EventDispatcher&lt;/code&gt; thread, where it
looks up the page&#8217;s scrolling tree, asks it for a &lt;code&gt;TrackingType&lt;/code&gt;, and splits
three ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NotTracking&lt;/strong&gt; &#8212; no listeners. Reply &lt;code&gt;handled = false&lt;/code&gt; immediately, without
bothering the main thread at all. The UI process can start scrolling right
away.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asynchronous&lt;/strong&gt; &#8212; passive listeners only, so nothing can cancel the event.
Reply &lt;code&gt;handled = false&lt;/code&gt; first so scrolling starts, then deliver the event to the main thread.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Synchronous&lt;/strong&gt; &#8212; a non-passive listener may call &lt;code&gt;preventDefault()&lt;/code&gt;, so wait
for the main thread result as before.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replying without a main thread round trip is possible because the new
&lt;code&gt;TouchEvent&lt;/code&gt; message is declared &lt;code&gt;AnyThread&lt;/code&gt; in &lt;code&gt;EventDispatcher.messages.in&lt;/code&gt;.
The iOS equivalent is &lt;code&gt;MainThreadCallback&lt;/code&gt;, which always replies from the main
thread.&lt;/p&gt;
&lt;p&gt;If there is no scrolling tree for the page yet, the event goes to the main
thread as before.&lt;/p&gt;
&lt;h3 id=&quot;classifying-a-touch-in-the-scrolling-tree&quot; tabindex=&quot;-1&quot;&gt;Classifying a touch in the scrolling tree &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The classification itself is
&lt;code&gt;ScrollingTreeCoordinated::eventTrackingTypeForTouchEvent()&lt;/code&gt;. It works in two
stages.&lt;/p&gt;
&lt;p&gt;First, for each newly pressed touch point: convert the point from view to contents coordinates,
hit test the layer tree down from the root contents layer, take the frontmost
layer whose event region contains the point, and query that region. It is queried
for many event types, because a touch fires more than the DOM &lt;code&gt;touch*&lt;/code&gt; events &#8212;
&lt;code&gt;pointer*&lt;/code&gt;, compatibility mouse events and &lt;code&gt;gesture*&lt;/code&gt; too, and a non-passive
listener for any of them forces synchronous handling. The results are folded into
a small &lt;code&gt;TouchEventTracking&lt;/code&gt; struct with four fields: start, move, end and
force-change.&lt;/p&gt;
&lt;p&gt;Second, the tracking type of the event as a whole is derived from the touch point
states, merging the per-field values. Merging picks the stronger of two types
(&lt;code&gt;NotTracking&lt;/code&gt; &amp;lt; &lt;code&gt;Asynchronous&lt;/code&gt; &amp;lt; &lt;code&gt;Synchronous&lt;/code&gt;), so if any single point needs
synchronous handling, the whole event is synchronous.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TouchEventTracking&lt;/code&gt; persists for the lifetime of a touch sequence and is reset
once all points are released, so the hit test done at &lt;code&gt;touchstart&lt;/code&gt; is reused for
the following &lt;code&gt;touchmove&lt;/code&gt;/&lt;code&gt;touchend&lt;/code&gt;. That guarantees a sequence never flips from
synchronous to asynchronous halfway through just because a finger moved off a
listener&#8217;s area.&lt;/p&gt;
&lt;h3 id=&quot;input-type-range&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;&amp;lt;input type=range&amp;gt;&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A slider handles touches internally even with no JavaScript listener, so looking
at the event region alone would classify it as &lt;code&gt;NotTracking&lt;/code&gt;.
&lt;code&gt;HTMLInputElement::updateTouchEventHandler()&lt;/code&gt; now sets the
&lt;code&gt;HasInternalTouchEventHandling&lt;/code&gt; flag on &lt;code&gt;EventTarget&lt;/code&gt; for range inputs, and
&lt;code&gt;StyleAdjuster&lt;/code&gt; turns that flag into the full set of touch region types for the
element.&lt;/p&gt;
&lt;h3 id=&quot;keeping-the-animation-running-on-the-scrolling-thread&quot; tabindex=&quot;-1&quot;&gt;Keeping the animation running on the scrolling thread &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last piece is in &lt;code&gt;ScrollingEffectsController::handleWheelEvent()&lt;/code&gt;. As shown
above, WPE synthesizes wheel events from touch gestures with precise deltas.
Precise-delta events only need &lt;code&gt;immediateScrollBy()&lt;/code&gt; to move the scroll
position &#8212; but then nothing drives screen updates while the main thread is busy.&lt;/p&gt;
&lt;p&gt;The fix is that, while a scroll gesture is in progress, a scroll animation is
also started &#8212; from one ULP short of the destination (&lt;code&gt;std::nextafter()&lt;/code&gt;) to the
destination. Visually it finishes instantly &#8212; the
real scroll is still done by &lt;code&gt;immediateScrollBy()&lt;/code&gt; &#8212; but a scroll animation is
now running, which starts display link monitoring and keeps compositing driven
regardless of the main thread.&lt;/p&gt;
&lt;h2 id=&quot;the-event-flow-summarized&quot; tabindex=&quot;-1&quot;&gt;The event flow, summarized &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/fujii/img/touch-async-scrolling-before.svg&quot; alt=&quot;The UI process sends the touch event to the web process main thread, which may
be blocked by JavaScript or layout. Only after the reply arrives does gesture
recognition synthesize a wheel event and scrolling
start.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;After (no listeners, or passive listeners only):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/fujii/img/touch-async-scrolling-after.svg&quot; alt=&quot;The UI process sends the touch event to the EventDispatcher thread of the web
process, which asks the scrolling tree and replies immediately without the main
thread, so gesture recognition synthesizes a wheel event and scrolling starts
right away. If passive listeners exist, the event is also delivered to the main
thread afterwards.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Where a non-passive listener exists, we still wait for the main thread as before.
The spec requires &lt;code&gt;preventDefault()&lt;/code&gt; to be honoured, so that is unavoidable.&lt;/p&gt;
&lt;h2 id=&quot;layout-test-updates&quot; tabindex=&quot;-1&quot;&gt;Layout test updates &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a side effect, the tests under &lt;code&gt;fast/events/touch/&lt;/code&gt; had to be updated.&lt;/p&gt;
&lt;p&gt;Event regions are &lt;strong&gt;computed during a rendering update and propagated to the
scrolling tree via the platform layer tree&lt;/strong&gt;. Which means a test like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;touchstart&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;tapSoon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// &#8592; the region has not been updated yet!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;taps immediately after registering the listener, while the scrolling tree still
believes there is no listener and returns &lt;code&gt;NotTracking&lt;/code&gt;. The event never reaches
the main thread and the test fails.&lt;/p&gt;
&lt;p&gt;A new &lt;code&gt;UIHelper.renderingComplete()&lt;/code&gt; was added for this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;renderingComplete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Wait for the platform layer tree to be updated&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UIHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;animationFrame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UIHelper&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;animationFrame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two animation frames are needed because the first one runs the rendering update
that computes the regions, and a second is needed for the result to reach the
layer tree.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; tabindex=&quot;-1&quot;&gt;Summary &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;On WPE and GTK both the layer tree and the scrolling tree live in the web
process (Coordinated Graphics), so the iOS touch asynchronous scrolling
implementation could not be reused directly.&lt;/li&gt;
&lt;li&gt;Instead, touch events were given the same shape that already works for wheel
events: ask the scrolling tree from the EventDispatcher thread.&lt;/li&gt;
&lt;li&gt;The keys were enabling touch event regions, and making the IPC reply
&lt;code&gt;AnyThread&lt;/code&gt; so it can be sent without waiting for the main thread.&lt;/li&gt;
&lt;li&gt;Anywhere the page has no non-passive listener, scrolling
now starts regardless of what the main thread is doing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;acknowledgements&quot; tabindex=&quot;-1&quot;&gt;Acknowledgements &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/fujii/asynchronous-scrolling-for-touch-events-in-wpe-and-webkitgtk/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many thanks to Alejandro G. Castro and Carlos Garcia Campos for their insightful
reviews of this work, and to Claude for writing this blog post.&lt;/p&gt;        </description>
	<pubDate>Sun, 13 Sep 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Pawel Lampe: Trying WPE Platform API on Raspberry Pi</title>
	<guid>https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/</guid>
	<link>https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/</link>
	<description>
&lt;p&gt;WPE Platform API (also known as &#8220;new API&#8221;) is a redesigned, GObject-based platform-integration layer for WPE WebKit that replaces the older &lt;code&gt;libwpe&lt;/code&gt; backend model. A few months ago, &lt;a href=&quot;https://blogs.igalia.com/klee&quot;&gt;Kate&lt;/a&gt; and
&lt;a href=&quot;https://simonpena.com/&quot;&gt;Simon&lt;/a&gt; published two closely related blog posts about it. The &lt;a href=&quot;https://blogs.igalia.com/klee/building-a-custom-html-context-menu-with-the-new-wpeplatform-api/&quot;&gt;first one&lt;/a&gt; focuses more on the API and browser
implementation details, while the &lt;a href=&quot;https://simonpena.com/blog/2026/03/20/getting-started-with-wpe-webkit/&quot;&gt;second one&lt;/a&gt; focuses more on writing and integrating the browser within Linux distribution.&lt;/p&gt;
&lt;p&gt;This article builds on top of the above ones, and showcases how to build and try a minimal WPE browser using WPE Platform API on &lt;a href=&quot;https://www.raspberrypi.com/&quot;&gt;Raspberry Pi&lt;/a&gt;. Moreover, as the WPE Platform API still evolves to some degree, this article
also explains how to use and stick to the latest WPE WebKit from &lt;code&gt;main&lt;/code&gt; branch. This way one can play with all the latest features straight on embedded hardware.&lt;/p&gt;
&lt;p&gt;Before going further, one should be aware that in case of a simple release build (instead of one using latest &lt;code&gt;main&lt;/code&gt; branch) it&#8217;s better to follow &lt;a href=&quot;https://github.com/Igalia/meta-webkit/wiki/RPi&quot;&gt;official instructions&lt;/a&gt; instead of this article.&lt;/p&gt;
&lt;h2 id=&quot;setup&quot; tabindex=&quot;-1&quot;&gt;Setup &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article focuses on a certain setup using &lt;a href=&quot;https://www.raspberrypi.com/products/raspberry-pi-3-model-b/&quot;&gt;Raspberry Pi 3B&lt;/a&gt; but it should be fairly easy to adapt the config to any other Raspberry Pi model.&lt;/p&gt;
&lt;p&gt;As for the work environment: the Linux-based host with ability to run containers was used along with &lt;a href=&quot;https://github.com/Igalia/wkdev-sdk&quot;&gt;WebKit Container SDK&lt;/a&gt;. The SDK version was precisely &lt;code&gt;2.53-v6-d535e88&lt;/code&gt; as it uses
&lt;code&gt;Ubuntu 24.04.4 LTS&lt;/code&gt; that works well with Yocto &lt;code&gt;scarthgap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Yocto &lt;code&gt;scarthgap&lt;/code&gt; has been used to increase the chances that the config and commands demonstrated in this article will remain buildable for many years to follow.&lt;/p&gt;
&lt;h2 id=&quot;preparing-the-image&quot; tabindex=&quot;-1&quot;&gt;Preparing the image &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The preparation of the image starts with a series of commands that create a main directory and clone important Yocto repositories along with some meta layer repositories. At this point already, &lt;strong&gt;it&#8217;s important to have the working directory shared
between host and SDK&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# host&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; wpe-upstream&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; wpe-upstream&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://git.yoctoproject.org/git/poky &lt;span class=&quot;token parameter variable&quot;&gt;-b&lt;/span&gt; scarthgap&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone git@github.com:openembedded/meta-openembedded.git &lt;span class=&quot;token parameter variable&quot;&gt;-b&lt;/span&gt; scarthgap&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://git.yoctoproject.org/git/meta-raspberrypi &lt;span class=&quot;token parameter variable&quot;&gt;-b&lt;/span&gt; scarthgap&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/Igalia/meta-webkit &lt;span class=&quot;token parameter variable&quot;&gt;-b&lt;/span&gt; scarthgap&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; poky/oe-init-build-env build&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the &lt;code&gt;build&lt;/code&gt; directory is created, it&#8217;s necessary to configure the meta layers in the &lt;code&gt;build/conf/bblayers.conf&lt;/code&gt; file the following way:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# changes incompatibly&lt;/span&gt;&lt;br /&gt;POKY_BBLAYERS_CONF_VERSION &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;BBPATH &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${TOPDIR}&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;BSPDIR :&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${@os.path.abspath(os.path.dirname(d.getVar('FILE'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; True)) + '&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;..&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;..')}&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;BBFILES ?&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;br /&gt;BBLAYERS ?&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/poky/meta \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/poky/meta-poky \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/poky/meta-yocto-bsp \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/meta-openembedded/meta-oe \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/meta-openembedded/meta-multimedia \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/meta-openembedded/meta-python \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/meta-raspberrypi \&lt;br /&gt;  &lt;span class=&quot;token variable&quot;&gt;${BSPDIR}&lt;/span&gt;/meta-webkit \&lt;br /&gt;  &quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the above, the recipes from the meta layers cloned earlier will be considered by bitbake.&lt;/p&gt;
&lt;p&gt;Next, the most important configuration step is appending the following to &lt;code&gt;build/conf/local.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;MACHINE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;raspberrypi3-64&quot;&lt;/span&gt; &lt;br /&gt;MACHINE_FEATURES:append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; vc4graphics&quot;&lt;/span&gt;&lt;br /&gt;GPU_MEM_256 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;128&quot;&lt;/span&gt;&lt;br /&gt;GPU_MEM_512 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;196&quot;&lt;/span&gt;&lt;br /&gt;GPU_MEM_1024 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;396&quot;&lt;/span&gt;&lt;br /&gt;DISTRO_FEATURES:append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; opengl egl wayland&quot;&lt;/span&gt;&lt;br /&gt;EXTRA_IMAGE_FEATURES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;debug-tweaks&quot;&lt;/span&gt;&lt;br /&gt;IMAGE_FEATURES:append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; ssh-server-dropbear hwcodecs&quot;&lt;/span&gt;&lt;br /&gt;IMAGE_INSTALL:append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; wpewebkit wpe-browser&quot;&lt;/span&gt;&lt;br /&gt;PREFERRED_VERSION_wpewebkit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;latest&quot;&lt;/span&gt;&lt;br /&gt;LICENSE_FLAGS_ACCEPTED &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;synaptics-killswitch&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that, &lt;strong&gt;wpewebkit latest&lt;/strong&gt; will be preferred and installed in the image along with a dummy browser called &lt;strong&gt;wpe-browser&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To make the &lt;strong&gt;wpewebkit latest&lt;/strong&gt; work, one needs to create &lt;code&gt;meta-webkit/recipes-browser/wpewebkit/wpewebkit_latest.bb&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;SUMMARY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Lightweight WebKit port for embedded devices with OpenGL-ES acceleration&quot;&lt;/span&gt;&lt;br /&gt;DESCRIPTION &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;WPE WebKit port pairs the WebKit engine with OpenGL-ES (OpenGL for Embedded Systems), \&lt;br /&gt;               allowing embedders to create simple and performant systems based on Web platform technologies. \&lt;br /&gt;               It is designed with hardware acceleration in mind, relying on EGL, and OpenGL ES.&quot;&lt;/span&gt;&lt;br /&gt;HOMEPAGE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://wpewebkit.org/&quot;&lt;/span&gt;&lt;br /&gt;BUGTRACKER &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugs.webkit.org/&quot;&lt;/span&gt;&lt;br /&gt;LICENSE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;BSD-2-Clause &amp;amp; LGPL-2.0-or-later&quot;&lt;/span&gt;&lt;br /&gt;LIC_FILES_CHKSUM &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file://Source/WebCore/LICENSE-LGPL-2.1;md5=a778a33ef338abbaf8b8a7c36b6eec80 &quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;REQUIRED_DISTRO_FEATURES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;opengl&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DEPENDS:append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; \&lt;br /&gt;    libsoup \&lt;br /&gt;    bison-native gperf-native harfbuzz-native libxml2-native ccache-native ninja-native ruby-native \&lt;br /&gt;    fontconfig freetype glib-2.0 harfbuzz icu jpeg pcre sqlite3 zlib libpng libtasn1 \&lt;br /&gt;    libwebp libxml2 libxslt virtual/egl virtual/libgles2 libepoxy libgcrypt \&lt;br /&gt;    unifdef-native \&lt;br /&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;inherit cmake features_check pkgconfig perlnative python3native&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; WK_USE_CCACHE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NO&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PACKAGECONFIG ??&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;accessibility avif dfg-jit gbm gpu-process \&lt;br /&gt;                   jit jpegxl libbacktrace \&lt;br /&gt;                   mediasource mediastream \&lt;br /&gt;                   remote-inspector \&lt;br /&gt;                   sysprof \&lt;br /&gt;                   &lt;span class=&quot;token variable&quot;&gt;${@' system-sysprof' \&lt;br /&gt;                       if bb.utils.contains('BBFILE_COLLECTIONS'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'meta-gnome'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; True&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; False&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d) \&lt;br /&gt;                       else '' }&lt;/span&gt; \&lt;br /&gt;                   unified-builds video webaudio woff2 wpe-platform \&lt;br /&gt;                   &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('DISTRO_FEATURES'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'systemd'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'journald'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; '' &lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt;d)}&lt;/span&gt; \&lt;br /&gt;                  &quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;reduce-size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DCMAKE_BUILD_TYPE=MinSizeRel,-DCMAKE_BUILD_TYPE=Release,,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;release-with-debug-info&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DCMAKE_BUILD_TYPE=RelWithDebInfo,-DCMAKE_BUILD_TYPE=Release,,&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# WPE features&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;accessibility&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_ATK=ON,-DUSE_ATK=OFF,atk at-spi2-atk&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;avif&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_AVIF=ON,-DUSE_AVIF=OFF,libavif&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;bubblewrap&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_BUBBLEWRAP_SANDBOX=ON -DBWRAP_EXECUTABLE=&lt;span class=&quot;token variable&quot;&gt;${bindir}&lt;/span&gt;/bwrap -DDBUS_PROXY_EXECUTABLE=&lt;span class=&quot;token variable&quot;&gt;${bindir}&lt;/span&gt;/xdg-dbus-proxy,-DENABLE_BUBBLEWRAP_SANDBOX=OFF,bubblewrap xdg-dbus-proxy libseccomp&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;developer-mode&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DDEVELOPER_MODE=ON,-DDEVELOPER_MODE=OFF,wayland-native wayland-protocols wpebackend-fdo&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;deviceorientation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_DEVICE_ORIENTATION=ON,-DENABLE_DEVICE_ORIENTATION=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dfg-jit&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_DFG_JIT=ON,-DENABLE_DFG_JIT=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;documentation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_DOCUMENTATION=ON,-DENABLE_DOCUMENTATION=OFF, gi-docgen-native gi-docgen&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;encryptedmedia&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_ENCRYPTED_MEDIA=ON,-DENABLE_ENCRYPTED_MEDIA=OFF,libgcrypt&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;experimental-features&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_EXPERIMENTAL_FEATURES=ON,-DENABLE_EXPERIMENTAL_FEATURES=OFF,libavif libjxl&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;gamepad&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_GAMEPAD=ON,-DENABLE_GAMEPAD=OFF,libmanette&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;gbm&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_GBM=ON,-DUSE_GBM=OFF,libdrm&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;geolocation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_GEOLOCATION=ON,-DENABLE_GEOLOCATION=OFF,geoclue&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;gpu-process&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_GPU_PROCESS=ON,-DENABLE_GPU_PROCESS=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hyphen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_LIBHYPHEN=ON,-DUSE_LIBHYPHEN=OFF,hyphen&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;introspection&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_INTROSPECTION=ON,-DENABLE_INTROSPECTION=OFF, gobject-introspection-native&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;jit&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_JIT=ON -DENABLE_C_LOOP=OFF,-DENABLE_JIT=OFF -DENABLE_C_LOOP=ON,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;jpegxl&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_JPEGXL=ON,-DUSE_JPEGXL=OFF,libjxl&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;journald&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_JOURNALD_LOG=ON,-DENABLE_JOURNALD_LOG=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lcms&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_LCMS=ON,-DUSE_LCMS=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;spellcheck&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_SPELLCHECK=ON,-DENABLE_SPELLCHECK=OFF,enchant&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wpe-legacy-api&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WPE_LEGACY_API=ON,-DENABLE_WPE_LEGACY_API=OFF,libwpe virtual/wpebackend,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;libbacktrace&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_LIBBACKTRACE=ON,-DUSE_LIBBACKTRACE=OFF,libbacktrace&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minibrowser&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_MINIBROWSER=ON,-DENABLE_MINIBROWSER=OFF,wayland-native wayland-protocols wpebackend-fdo&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mediasource&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_MEDIA_SOURCE=ON,-DENABLE_MEDIA_SOURCE=OFF,gstreamer1.0 gstreamer1.0-plugins-good&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mediastream&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_MEDIA_STREAM=ON,-DENABLE_MEDIA_STREAM=OFF,gstreamer1.0 gstreamer1.0-plugins-bad&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pdfjs&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_PDFJS=ON,-DENABLE_PDFJS=OFF,&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;speech-synthesis&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_SPEECH_SYNTHESIS=ON,-DENABLE_SPEECH_SYNTHESIS=OFF,flite&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sysprof&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_SYSPROF_CAPTURE=ON, -DUSE_SYSPROF_CAPTURE=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;system-sysprof&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_SYSTEM_SYSPROF_CAPTURE=ON, -DUSE_SYSTEM_SYSPROF_CAPTURE=OFF, sysprof&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;video&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_VIDEO=ON,-DENABLE_VIDEO=OFF,gstreamer1.0 gstreamer1.0-plugins-base&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;webaudio&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WEB_AUDIO=ON,-DENABLE_WEB_AUDIO=OFF,gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;woff2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DUSE_WOFF2=ON,-DUSE_WOFF2=OFF,woff2&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;remote-inspector&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_REMOTE_INSPECTOR=ON,-DENABLE_REMOTE_INSPECTOR=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;webrtc&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WEB_RTC=ON,-DENABLE_WEB_RTC=OFF,libvpx libevent libopus openh264&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;qtwpe&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WPE_QT_API=ON &lt;span class=&quot;token variable&quot;&gt;${CMAKE_QT_OECONF}&lt;/span&gt;,-DENABLE_WPE_QT_API=OFF,qtbase-native qtbase qtdeclarative libepoxy wpebackend-fdo &lt;span class=&quot;token variable&quot;&gt;${QT_BUILD_DEPS}&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;unified-builds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_UNIFIED_BUILDS=ON,-DENABLE_UNIFIED_BUILDS=OFF,&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;thunder&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_THUNDER=ON,-DENABLE_THUNDER=OFF,virtual/open-cdm&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;webxr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WEBXR=ON,-DENABLE_WEBXR=OFF,openxr&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Build option for WPE API 1.1&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wpe-1-1-api&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WPE_1_1_API:BOOL=ON,-DENABLE_WPE_1_1_API:BOOL=OFF,&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Build option for WPE platform API&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;wpe-platform&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-DENABLE_WPE_PLATFORM=ON,-DENABLE_WPE_PLATFORM=OFF,libinput libxkbcommon wayland-native&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;EXTRA_OECMAKE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; -DPORT=WPE -G Ninja&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# TODO: documentation and introspection are disabled by default because the are&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# causing cross-compiling build errors&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# PACKAGECONFIG:append = &quot; ${@bb.utils.contains('DISTRO_FEATURES', 'api-documentation', 'documentation', '' ,d)} introspection&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# If SSE code compiles, assume it runs successfully (it can't actually run&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# because of cross compiling)&lt;/span&gt;&lt;br /&gt;EXTRA_OECMAKE:append:x86 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; -DHAVE_SSE2_EXTENSIONS_EXITCODE=0&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Javascript JIT is not supported on ppc/arm/RISCV32/mips64&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:powerpc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:powerpc64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:powerpc64le &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:armv4 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:armv5 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:armv6 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:armv7a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:armv7ve &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:riscv32 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:riscv64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:mipsarchn64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:mipsarchn32 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:loongarch64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Javascript JIT is not supported on x86&lt;/span&gt;&lt;br /&gt;PACKAGECONFIG:remove:x86 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jit&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;LDFLAGS:append:riscv64 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; -pthread&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;FULL_OPTIMIZATION:remove &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-g&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;LEAD_SONAME &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;libWPEWebKit.so&quot;&lt;/span&gt;&lt;br /&gt;PACKAGES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;+ &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-web-inspector-plugin &lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-qtwpe-qml-plugin&quot;&lt;/span&gt;&lt;br /&gt;FILES:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${libdir}&lt;/span&gt;/wpe-webkit*/injected-bundle/libWPEInjectedBundle.so&quot;&lt;/span&gt;&lt;br /&gt;FILES:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-web-inspector-plugin &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${datadir}&lt;/span&gt;/wpe-webkit-*/inspector.gresource&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# nooelint: oelint.vars.insaneskip - ignored for convenience. We need to recheck if problem persist&lt;/span&gt;&lt;br /&gt;INSANE_SKIP:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-web-inspector-plugin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dev-so&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# nooelint: oelint.vars.insaneskip - ignored for convenience. We need to recheck if problem persist&lt;/span&gt;&lt;br /&gt;INSANE_SKIP:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-qtwpe-qml-plugin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dev-so&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# JSC JIT on ARMv7 is better supported with Thumb2 instruction set.&lt;/span&gt;&lt;br /&gt;ARM_INSTRUCTION_SET:armv7a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;thumb&quot;&lt;/span&gt;&lt;br /&gt;ARM_INSTRUCTION_SET:armv7r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;thumb&quot;&lt;/span&gt;&lt;br /&gt;ARM_INSTRUCTION_SET:armv7m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;thumb&quot;&lt;/span&gt;&lt;br /&gt;ARM_INSTRUCTION_SET:armv7ve &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;thumb&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Extra runtime depends&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# nooelint: oelint.vars.dependsordered - ignored for convenience&lt;/span&gt;&lt;br /&gt;RDEPENDS:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'remote-inspector'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; '${PN}&lt;/span&gt;-web-inspector-plugin', '', d)} \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gst_gl'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gstreamer1.0-plugins-base-opengl'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; ''&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d)}&lt;/span&gt; \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'mediasource'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gstreamer1.0-plugins-good-isomp4'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; ''&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d)}&lt;/span&gt; \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'webaudio'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gstreamer1.0-plugins-good-wavparse'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; ''&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d)}&lt;/span&gt; \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'video'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gstreamer1.0-plugins-base-app \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-audioconvert \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-audioresample \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-gio \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-playback \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-typefindfunctions \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-videoconvertscale \&lt;br /&gt;                                                    gstreamer1.0-plugins-base-volume \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-audiofx \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-audioparsers \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-autodetect \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-avi \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-deinterlace \&lt;br /&gt;                                                    gstreamer1.0-plugins-good-interleave \&lt;br /&gt;                                                    '&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; ''&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d)}&lt;/span&gt; \&lt;br /&gt;    libgles2 \&lt;br /&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;RDEPENDS:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-web-inspector-plugin &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\&lt;br /&gt;    shared-mime-info \&lt;br /&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Extra runtime recommends&lt;/span&gt;&lt;br /&gt;RRECOMMENDS:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\&lt;br /&gt;    ca-certificates \&lt;br /&gt;    ttf-dejavu-sans \&lt;br /&gt;    ttf-dejavu-sans-mono \&lt;br /&gt;    ttf-dejavu-serif \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;-qtwpe-qml-plugin \&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;${@bb.utils.contains('PACKAGECONFIG'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'video'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; 'gstreamer1.0-plugins-base-meta gstreamer1.0-plugins-good-meta gstreamer1.0-plugins-bad-meta'&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; ''&lt;span class=&quot;token operator&quot;&gt;,&lt;/span&gt; d)}&lt;/span&gt; \&lt;br /&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DEFAULT_PREFERENCE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-1&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;FILESEXTRAPATHS:prepend :&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${THISDIR}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt;:&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# https://commits.webkit.org/319279@main&lt;/span&gt;&lt;br /&gt;PR &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;r319279&quot;&lt;/span&gt;&lt;br /&gt;SRCREV &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;93472ec12ee947b30c7ec3c176ca0e2fb6ba6ace&quot;&lt;/span&gt;&lt;br /&gt;SRC_URI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;git://github.com/WebKit/WebKit.git;protocol=https;branch=main \&lt;br /&gt;           file://0001-libpas-Only-include-stdatomic.h-when-compiling-with.patch \&lt;br /&gt;           file://0002-WebDriver-Guard-LOG_CHANNEL-check-with-LOG_DISABLED.patch \&lt;br /&gt;           &quot;&lt;/span&gt;&lt;br /&gt;S &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${WORKDIR}&lt;/span&gt;/git&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This file is self-contained on purpose; the idea is not to rely on any includes so that unpredictable behavior doesn&#8217;t happen in the future.&lt;/p&gt;
&lt;p&gt;While the above file contains a lot of interesting details, the most interesting practical part is the last few lines. The &lt;code&gt;SRCREV&lt;/code&gt; is set to point to the latest commit from the &lt;a href=&quot;https://github.com/WebKit/WebKit&quot;&gt;WebKit&lt;/a&gt; &lt;code&gt;main&lt;/code&gt; branch (at the time
of writing). Along with that comes &lt;code&gt;SRC_URI&lt;/code&gt; that specifies two patches required to make WPE WebKit compile.&lt;/p&gt;
&lt;p&gt;The problem with the patches is that advancing &lt;code&gt;SRCREV&lt;/code&gt; will likely make them unusable due to merge conflicts. Therefore, when advancing the revision, it&#8217;s recommended to remove patches from &lt;code&gt;SRC_URI&lt;/code&gt; and face the compilation problems from scratch as
it&#8217;s very likely there will be new compilation problems anyway. Fortunately, nowadays LLMs can be used to fix any compilation problems by preparing custom patches just like the below ones (created by LLM as well). For example, most of the modern
models should manage to prepare proper patches just by pointing them to the above recipe and the &lt;code&gt;temp&lt;/code&gt; directory with the latest logs from build commands.&lt;/p&gt;
&lt;p&gt;Assuming one uses the &lt;code&gt;wpewebkit_latest.bb&lt;/code&gt; above, the first patch needs to be created in: &lt;code&gt;meta-webkit/recipes-browser/wpewebkit/wpewebkit/0001-libpas-Only-include-stdatomic.h-when-compiling-with.patch&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pawel Lampe &amp;lt;plampe@igalia.com&amp;gt;
Date: Mon, 17 Aug 2026 00:00:00 +0000
Subject: [PATCH] [libpas] Only include stdatomic.h when compiling with Clang

Some libpas .c files (e.g. jit_heap.c) are compiled as C++ via
set_source_files_properties(... PROPERTIES LANGUAGE CXX) in
Source/bmalloc/CMakeLists.txt, for TZone heap support. pas_utils.h
unconditionally does `#include &amp;lt;stdatomic.h&amp;gt;`, but GCC's own
&amp;lt;stdatomic.h&amp;gt; relies on the C11-only `_Atomic` keyword and has no
support for being included from C++ translation units (this was only
addressed in much newer GCC releases). Compiling any of the
CXX-tagged libpas .c files with GCC 13 therefore fails with:

    error: '_Atomic' does not name a type

The header is only actually needed here for the Clang-specific
__c11_atomic_* intrinsics guarded by `#elif PAS_COMPILER(CLANG)`
further down in this file; the non-Clang (GCC) path uses the
__atomic_* builtins instead and does not need any of the types or
macros from &amp;lt;stdatomic.h&amp;gt;. Guard the include accordingly so GCC
builds (both plain C and the CXX-tagged libpas sources) are
unaffected by GCC's non-C++-aware &amp;lt;stdatomic.h&amp;gt;.

Upstream-Status: Pending
Signed-off-by: Pawel Lampe &amp;lt;plampe@igalia.com&amp;gt;
---
 Source/bmalloc/libpas/src/libpas/pas_utils.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Source/bmalloc/libpas/src/libpas/pas_utils.h b/Source/bmalloc/libpas/src/libpas/pas_utils.h
index 962634080930..9b98fda54f43 100644
--- a/Source/bmalloc/libpas/src/libpas/pas_utils.h
+++ b/Source/bmalloc/libpas/src/libpas/pas_utils.h
@@ -42,7 +42,15 @@
 #endif
 
 #include &amp;lt;limits.h&amp;gt;
+#if PAS_COMPILER(CLANG)
+/* GCC's &amp;lt;stdatomic.h&amp;gt; relies on the C-only _Atomic keyword and is not
+ * usable when this header is included from a translation unit compiled
+ * as C++ (some libpas .c files are compiled as C++, see bmalloc's
+ * CMakeLists.txt). It is only needed here for the Clang-specific
+ * __c11_atomic_* intrinsics below; the GCC path uses __atomic_* builtins
+ * instead. */
 #include &amp;lt;stdatomic.h&amp;gt;
+#endif
 #include &amp;lt;stdbool.h&amp;gt;
 #include &amp;lt;stdint.h&amp;gt;
 #include &amp;lt;string.h&amp;gt;
--
2.43.0


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second patch should be: &lt;code&gt;meta-webkit/recipes-browser/wpewebkit/wpewebkit/0002-WebDriver-Guard-LOG_CHANNEL-check-with-LOG_DISABLED.patch&lt;/code&gt; with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pawel Lampe &amp;lt;plampe@igalia.com&amp;gt;
Date: Mon, 17 Aug 2026 00:00:00 +0000
Subject: [PATCH] [WebDriver] Guard LOG_CHANNEL check with
 LOG_DISABLED/RELEASE_LOG_DISABLED

WebDriverService::handleRequest() unconditionally checks
LOG_CHANNEL(WebDriverClassic).state to decide whether it is worth
building the request/response log strings. However,
Source/WebDriver/Logging.h only declares the WebDriverClassic (and
other WebDriver) log channels inside:

    #if !LOG_DISABLED || !RELEASE_LOG_DISABLED

On a release build (NDEBUG, so LOG_DISABLED is true) without journald
support and without OS_LOG/Android (so RELEASE_LOG_DISABLED is also
true) - the common configuration for an embedded Linux build without
the &amp;quot;journald&amp;quot; PACKAGECONFIG - that guard is false, so the channel is
never declared, and this direct, unguarded use of LOG_CHANNEL() fails
to compile:

    error: 'LOG_CHANNEL_PREFIXWebDriverClassic' was not declared in this scope

RELEASE_LOG_INFO() itself already collapses to a no-op in that
configuration (see wtf/Assertions.h), so guard this manual
LOG_CHANNEL() state check with the same condition used to declare the
channel in Logging.h.

Upstream-Status: Pending
Signed-off-by: Pawel Lampe &amp;lt;plampe@igalia.com&amp;gt;
---
 Source/WebDriver/WebDriverService.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Source/WebDriver/WebDriverService.cpp b/Source/WebDriver/WebDriverService.cpp
index 07ae385f33f4..2612d239a611 100644
--- a/Source/WebDriver/WebDriverService.cpp
+++ b/Source/WebDriver/WebDriverService.cpp
@@ -381,6 +381,7 @@ bool WebDriverService::findCommand(HTTPMethod method, const String&amp;amp; path, Comman
 void WebDriverService::handleRequest(HTTPRequestHandler::Request&amp;amp;&amp;amp; request, Function&amp;lt;void (HTTPRequestHandler::Response&amp;amp;&amp;amp;)&amp;gt;&amp;amp;&amp;amp; replyHandler)
 {
     Function&amp;lt;void (HTTPRequestHandler::Response&amp;amp;&amp;amp;)&amp;gt; actualReplyHandler = WTF::move(replyHandler);
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
     if (LOG_CHANNEL(WebDriverClassic).state != WTFLogChannelState::Off) {
         RELEASE_LOG_INFO(WebDriverClassic, &amp;quot;HTTP request %s %s (body=%zu bytes)&amp;quot;, request.method.utf8().data(), request.path.utf8().data(), request.dataLength);
         actualReplyHandler = [startTime = MonotonicTime::now(), replyHandler = WTF::move(actualReplyHandler)](HTTPRequestHandler::Response&amp;amp;&amp;amp; response) mutable {
@@ -388,6 +389,7 @@ void WebDriverService::handleRequest(HTTPRequestHandler::Request&amp;amp;&amp;amp; request, Func
             replyHandler(WTF::move(response));
         };
     }
+#endif
 
     auto method = toCommandHTTPMethod(request.method);
     if (!method) {
--
2.43.0

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the patches are added, &lt;strong&gt;wpewebkit latest&lt;/strong&gt; should build correctly. However, to make use of it one needs a browser.&lt;/p&gt;
&lt;p&gt;To demonstrate how easy the browser for WPE WebKit with Platform API can be, a very minimalistic one will be prepared below.&lt;/p&gt;
&lt;p&gt;The first step is to create a directory:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; meta-webkit/recipes-browser/wpe-browser/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then a file: &lt;code&gt;meta-webkit/recipes-browser/wpe-browser/main.cpp&lt;/code&gt; that implements the whole browser:&lt;/p&gt;
&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;wpe/webkit.h&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;g_autoptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GMainLoop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; loop &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;g_main_loop_new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;g_autoptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WebKitWebView&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; view &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;WEBKIT_WEB_VIEW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;g_object_new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WEBKIT_TYPE_WEB_VIEW&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;webkit_web_view_load_uri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;view&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://wpewebkit.org&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;g_main_loop_run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; EXIT_SUCCESS&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then a file: &lt;code&gt;meta-webkit/recipes-browser/wpe-browser/CMakeLists.txt&lt;/code&gt; that describes how to build it:&lt;/p&gt;
&lt;pre class=&quot;language-cmake&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cmake&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;cmake_minimum_required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;VERSION&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wpe-browser CXX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;CMAKE_CXX_STANDARD&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GNUInstallDirs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;find_package&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PkgConfig REQUIRED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# The Wayland WPE Platform already depends on wpe-platform-2.0&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;pkg_check_modules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WebKitDeps REQUIRED&lt;br /&gt;    IMPORTED_TARGET&lt;br /&gt;    wpe-webkit-&lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;&lt;br /&gt;    wpe-platform-wayland-&lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;add_executable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wpe-browser main.cpp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;target_link_libraries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wpe-browser&lt;br /&gt;    &lt;span class=&quot;token namespace&quot;&gt;PRIVATE&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token inserted class-name&quot;&gt;PkgConfig::WebKitDeps&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TARGETS wpe-browser RUNTIME DESTINATION &lt;span class=&quot;token punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;CMAKE_INSTALL_BINDIR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and finally a recipe file: &lt;code&gt;meta-webkit/recipes-browser/wpe-browser/wpe-browser_1.0.bb&lt;/code&gt; that allows bitbake to build the browser and install it in the image:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;SUMMARY &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Minimal WPE WebKit browser launcher&quot;&lt;/span&gt;&lt;br /&gt;DESCRIPTION &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A minimal launcher built on the WPE Platform API, displaying \&lt;br /&gt;               a URL given as its only argument (defaults to https://wpewebkit.org). \&lt;br /&gt;               Based on https://simonpena.com/blog/2026/03/20/getting-started-with-wpe-webkit/&quot;&lt;/span&gt;&lt;br /&gt;HOMEPAGE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://simonpena.com/blog/2026/03/20/getting-started-with-wpe-webkit/&quot;&lt;/span&gt;&lt;br /&gt;LICENSE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MIT&quot;&lt;/span&gt;&lt;br /&gt;LIC_FILES_CHKSUM &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file://&lt;span class=&quot;token variable&quot;&gt;${COMMON_LICENSE_DIR}&lt;/span&gt;/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;FILESEXTRAPATHS:prepend :&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${THISDIR}&lt;/span&gt;:&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;SRC_URI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file://main.cpp \&lt;br /&gt;           file://CMakeLists.txt \&lt;br /&gt;          &quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;S &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${WORKDIR}&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DEPENDS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wpewebkit&quot;&lt;/span&gt;&lt;br /&gt;RDEPENDS:&lt;span class=&quot;token variable&quot;&gt;${PN}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wpewebkit&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;inherit cmake pkgconfig features_check&lt;br /&gt;&lt;br /&gt;REQUIRED_DISTRO_FEATURES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;opengl wayland&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After all those steps, everything is ready to perform a build. This time the commands are executed in the &lt;strong&gt;SDK&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; poky/oe-init-build-env build&lt;br /&gt;bitbake core-image-weston&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; tmp/deploy/images/raspberrypi3-64/&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# flash to SD card based on preference&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;trying-the-image&quot; tabindex=&quot;-1&quot;&gt;Trying the image &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once the image is built and flashed to SD card, and the SD card has been used to boot the Raspberry Pi, one can SSH into it, basically by:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ssh&lt;/span&gt; root@&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IP&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, the browser should work out of the box. The first command to try is the one that doesn&#8217;t need the network and therefore is the simplest:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;XDG_RUNTIME_DIR&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/run/user/1000 &lt;span class=&quot;token assign-left variable&quot;&gt;WAYLAND_DISPLAY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;wayland-1 wpe-browser &lt;span class=&quot;token string&quot;&gt;'webkit://gpu/stdout'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the network is available, it&#8217;s worth starting simple and loading some HTTP page:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;XDG_RUNTIME_DIR&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/run/user/1000 &lt;span class=&quot;token assign-left variable&quot;&gt;WAYLAND_DISPLAY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;wayland-1 wpe-browser &lt;span class=&quot;token string&quot;&gt;'http://info.cern.ch'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If that works as well, one can try the HTTPS one:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;XDG_RUNTIME_DIR&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/run/user/1000 &lt;span class=&quot;token assign-left variable&quot;&gt;WAYLAND_DISPLAY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;wayland-1 wpe-browser &lt;span class=&quot;token string&quot;&gt;'https://igalia.com'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If there&#8217;s an issue with certificates, it&#8217;s likely due to broken date/time, so the correct one needs to be set using a command like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;'2026-09-02 22:34:56'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusions&quot; tabindex=&quot;-1&quot;&gt;Conclusions &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/trying-wpe-platform-api-on-raspberry-pi/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since the Platform API is the future of WPE, it&#8217;s worth using it already. As the above sections demonstrate, it hasn&#8217;t ever been easier to create a WPE-powered browser for embedded hardware. Moreover, nowadays as LLMs are at play,
using latest sources from &lt;code&gt;main&lt;/code&gt; branch and quickly patching on demand is a possibility worth utilizing. With that, a broad sea of experimenting possibilities becomes wide open. However, it must not be forgotten that while &lt;code&gt;main&lt;/code&gt; branch
is great for testing new web platform features implemented in WebKit, it&#8217;s not necessarily ideal for testing performance. In such case, it&#8217;s better to rely on releases and proper browser engine fine tuning for particular hardware one
plays with.&lt;/p&gt;        </description>
	<pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #76</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-76/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-76/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from August 31 to September 7.&lt;/p&gt;
&lt;p&gt;
This was another week focused on ironing out graphics issues in preparation
for the upcoming 2.54.x release series. Did we say release? Here we have
another set of packaged release candidates as well!
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The &#8220;paint flushing&#8221; feature of the Web Inspector that shows the areas of the
layers that were painted &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320494@main&quot;&gt;is now
available&lt;/a&gt;. On the other hand, setting
&lt;code&gt;WEBKIT_SHOW_DAMAGE=1&lt;/code&gt; in the environment will show the areas of the window
that were rendered. For example, if the page is scrolled a little, the whole
window is rendered, but no layer has to be repainted.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Fixed &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320490@main&quot;&gt;visible pixel snapping&lt;/a&gt; in the
GTK and WPE ports' Skia compositor by choosing linear instead of
nearest-neighbor sampling for backing store tiles whenever a layer's transform
no longer maps tile pixels onto screen pixels 1:1, matching what the Texture
Mapper backend already got from its always-linear OpenGL code path.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320607@main&quot;&gt;Fixed&lt;/a&gt; a clipping bug in the
Skia-based compositor that caused layers with &lt;code&gt;overflow: hidden&lt;/code&gt; set to
not clip blur and box-shadow filter outsets.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320398@main&quot;&gt;Fixed a repaint bug&lt;/a&gt; where content
changing behind an element with a software-rendered filter such as &lt;code&gt;blur()&lt;/code&gt;
could leave stale pixels on screen, as with the glow effect that YouTube draws
around videos in dark/ambient mode. The fix restores proper tracking of which
layers act as the repaint container for a pixel-moving filter, so the repaint
area is expanded correctly again on WPE, GTK and macOS.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320612@main&quot;&gt;few&lt;/a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320617@main&quot;&gt;problems&lt;/a&gt; with Offscreen Canvas have
been fixed.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;releases-package&quot;&gt;Releases &#128230;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Release candidates &lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/09/02/webkitgtk2.53.92-released.html&quot;&gt;WebKitGTK
2.53.92&lt;/a&gt; and
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.53.92.html&quot;&gt;WPE WebKit 2.53.92&lt;/a&gt; have
been published, and they include polishing and a number of fixes that ensure
that there will not be noticeable regressions brought in by the new Skia-based
compositor and the damage tracking support&#8212;two of the main features of the
upcoming stable release series. As the stable release dates approaches, we
encourage people who try these preview versions to &lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/&quot;&gt;report issues in
Bugzilla&lt;/a&gt;.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 07 Sep 2026 23:43:23 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #75</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-75/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-75/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from August 24 to August 31.&lt;/p&gt;
&lt;p&gt;
After such a packed edition last week, we can relax with an even more
packed installment this week! The team has been moving full steam ahead
with the Layer-Based SVG Engine, and graphics improvements in general,
but we also had a handful of other updates, such as SDK updates, a new
WebsitePolicies API, and more.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320069@main&quot;&gt;Add&lt;/a&gt; new ChildChange types for moveBefore(). This addresses issues with the in-progress moveBefore() implementation where scripts would sometimes execute erroneously.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/pull/72789&quot;&gt;Added&lt;/a&gt; &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/color#alpha&quot;&gt;alpha channel&lt;/a&gt; support to color input choosers.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/8ce95bb31076b2a39f7450cb0018f30da1294a58&quot;&gt;Fixed&lt;/a&gt; Service Worker &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes&quot;&gt;static routes&lt;/a&gt; on non-Apple ports.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/b2678ccf7efb04a68ae229eff8edfc8c98ed402e&quot;&gt;Added&lt;/a&gt; a &lt;code&gt;WebsitePolicies:upgrade-to-https-policy&lt;/code&gt; property. When enabled this policy will automatically try using HTTPS even for HTTP websites (excluding localhost or IPs). The policy can be configured either to allow automatically falling back to HTTP if that fails, or to consider all HTTPS failures fatal for the best security.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319445@main&quot;&gt;Fixed SVG text being rasterized for the wrong resolution&lt;/a&gt; in zoomed standalone SVG documents in the Layer-Based SVG Engine (LBSE). &lt;code&gt;vector-effect: non-scaling-stroke&lt;/code&gt; on &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; no longer comes out too thick, and the resulting metrics match the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320045@main&quot;&gt;Fixed viewport clipping&lt;/a&gt; in the Layer-Based SVG Engine (LBSE), where a nested &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; or a &lt;code&gt;&amp;lt;marker&amp;gt;&lt;/code&gt; applied its viewport clip even when its content already fitted inside, and since that clip is not pixel-snapped its edge could fall between two device pixels and cut into whatever was drawn right at the viewport border. Painting now skips a clip that removes nothing, which eliminates a class of subtle pixel differences against the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319773@main&quot;&gt;Fixed opacity animations not damaging descendant layers&lt;/a&gt; in the GTK and WPE ports, where a descendant that paints outside its parent's bounds kept its stale pixels on screen. The mask-specific damage handling was generalized into a single group-property path shared by &lt;code&gt;opacity&lt;/code&gt;, filters, mask blend modes and replicas, which now damages the layer plus the overlap region of its whole subtree.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320143@main&quot;&gt;Added a &lt;code&gt;cycle-analysis&lt;/code&gt; subcommand&lt;/a&gt; to &lt;code&gt;webkit-sysprof&lt;/code&gt;, which draws every frame cycle of a capture as a bar of cells colored by the mark covering that moment on the main thread, showing whether a slow frame stalled on layout, a long timer or rasterization instead of only reporting that it was slow.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320144@main&quot;&gt;Removed redundant text updates&lt;/a&gt; for the text children of elements using &lt;code&gt;display: contents&lt;/code&gt;, which previously got one on every style resolution regardless of whether their style actually changed. This removes dozens of useless updates per style recalculation in Web Component applications, where every &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; uses &lt;code&gt;display: contents&lt;/code&gt;.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319866@main&quot;&gt;Fixed tile image caching&lt;/a&gt; in the Skia compositor by regenerating the cached &lt;code&gt;SkImage&lt;/code&gt; whenever a a tile's contents are updated and by adding a texture release callback that keeps the texture valid for as long as the image references it.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319943@main&quot;&gt;Switched video DMA-BUF buffers to Skia promise images&lt;/a&gt; in the Skia compositor, so the texture backing a video frame is only created at the point Skia actually draws it, which works for these buffers because the underlying &lt;code&gt;DMABufBuffer&lt;/code&gt; can be kept alive until the promise image is released.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319850@main&quot;&gt;Fixed a hang&lt;/a&gt; in the Layer-Based SVG Engine (LBSE) when two SVG &lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; elements reference each other through &lt;code&gt;href&lt;/code&gt;, or one references itself: collecting the inherited pattern attributes now remembers which patterns it has already visited, the same cycle detection that gradients have always had. The walk also resolves every reference in the tree scope of the pattern it started from, so a pattern referenced from inside a shadow tree now inherits the right attributes.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319545@main&quot;&gt;Skipped anchor-positioning bookkeeping&lt;/a&gt; during style resolution when a document uses no anchor positioning at all, avoiding two hash lookups per styled element.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319468@main&quot;&gt;Cached the SVG viewport size&lt;/a&gt; used to resolve lengths in the Layer-Based SVG Engine (LBSE), instead of recomputing the nearest &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element's view box rectangle once per shape per frame. The viewport is invariant across a flush and identical for every shape under the same &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt;, so caching removes redundant work.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319940@main&quot;&gt;Removed the code path for GPU rendering without Deferred Display Lists (DDL)&lt;/a&gt; in the Skia compositor, so accelerated painting always records into a display list and no longer needs to create GL contexts on worker threads.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/320152@main&quot;&gt;Fixed red and blue appearing swapped&lt;/a&gt; in non-accelerated video with the Skia compositor, by allocating the video frame's &lt;code&gt;BitmapTexture&lt;/code&gt; with the BGRA layout flag and applying that flag when the buffer is turned into a Skia image.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;infrastructure-construction-site&quot;&gt;Infrastructure &#127959;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319870@main&quot;&gt;Bumped the GTK and WPE developer SDK&lt;/a&gt; from v9 to v11, bringing GStreamer 1.28.5, sparkle-cdm 2026.2 and libsoup 3.7.2. Be sure to update your local wkdev-sdk container using &lt;code&gt;wkdev-update&lt;/code&gt; to make sure your development environment matches what the CI is testing.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 31 Aug 2026 20:12:08 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #74</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-74/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-74/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from August 17 to August 24.&lt;/p&gt;
&lt;p&gt;
Another periodical packed with updates on the graphics, multimedia, and
tooling fronts. Which sure has to do with preparing for the upcoming 2.54.x
release series, that now has release candidates published. Also, do not miss
a new stable release being published with fixes for security issues, and
make sure to update.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=207209&quot;&gt;Fixed&lt;/a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=315925&quot;&gt;flakiness&lt;/a&gt; in the Web
Inspector heap snapshot tests.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319307@main&quot;&gt;Extended&lt;/a&gt; the &lt;code&gt;webkit-sysprof analyze&lt;/code&gt;
tool cover the remaining marks emitted along the rendering pipeline, from
&lt;code&gt;RenderTreeBuild&lt;/code&gt; and &lt;code&gt;CompositingUpdate&lt;/code&gt; through &lt;code&gt;FinalizeRenderingUpdate&lt;/code&gt;,
&lt;code&gt;RenderLayerTree&lt;/code&gt; and &lt;code&gt;WaitForCompositionCompletion&lt;/code&gt; down to the individual
tile marks, pulling the tile count and the dirty region out of the mark
messages as statistics next to the durations. The statistics tables also gained
mean and median columns, so a captured trace now shows where the time in a
frame actually goes.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=225423&quot;&gt;Fixed&lt;/a&gt; test
&lt;code&gt;fast/canvas/canvas-composite-text-alpha.html&lt;/code&gt;, and improved the state of
several other tests which relied on &lt;code&gt;setTimeout()&lt;/code&gt;.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319475@main&quot;&gt;Implemented moving steps&lt;/a&gt; for
&lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319347@main&quot;&gt;Add support for asynchronous scrolling with touch
events&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Touch events are now dispatched to the &lt;code&gt;EventDispatcher&lt;/code&gt; thread in the Web
Process, enabling smooth scrolling even when the main thread is busy.
Additionally, this change fixed a bug where precise scrolling delta wheel
events, dispatched by touchpads, failed to trigger asynchronous scrolling.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Fixed several accessibility related tests and added support for missing
keywords in the GLib-based ports (GTK &amp;amp; WPE):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=213874&quot;&gt;[GLIB] accessibility/keyevents-posted-for-increment-actions.html times out&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=322020&quot;&gt;[GLIB][a11y] WTR: Add missing implementation of takeFocus&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=322007&quot;&gt;[GLIB][a11y] WTR: Add missing implementation of dismiss&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=322094&quot;&gt;[GLIB][a11y] WTR: Add missing implementation of focusableAncestor&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;


&lt;h3 id=&quot;multimedia-movie-camera&quot;&gt;Multimedia &#127909;&lt;/h3&gt;
&lt;div class=&quot;wip-description&quot;&gt;
&lt;p&gt;GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.&lt;/p&gt;
&lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/pull/70123&quot;&gt;Ensure&lt;/a&gt; that multimedia on pages
restored from the back-forward cache is correctly processed without errors or
reloading.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The robustness level is now &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319531@main&quot;&gt;queried from the
CDM&lt;/a&gt; (if supported) when using
Encrypted Media Extensions (EME).&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Added video rendering &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319367@main&quot;&gt;support for Qualcomm hardware-accelerated
decoders&lt;/a&gt; when the Skia compositor is
in use, complementing the &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/307174@main&quot;&gt;earlier TextureMapper-only
support&lt;/a&gt; that left such videos blank
with the new compositor.&lt;/p&gt;
&lt;p&gt;Video frame processing now relies on the driver's implicit YUV to RGB
conversion, steered by the colour space and sample range hints taken from the
frame colorimetry, with a hint-free import as fallback.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319388@main&quot;&gt;Fixed how &lt;code&gt;&amp;lt;feImage&amp;gt;&lt;/code&gt; paints its referenced
element&lt;/a&gt; in the Layer-Based SVG Engine
(LBSE), which still used a helper written for the legacy SVG engine, where SVG
content never had layers, so it used to paint renderers directly and skipped
any child that owns a &lt;code&gt;RenderLayer&lt;/code&gt; under LBSE, silently dropping its
&lt;code&gt;opacity&lt;/code&gt;, mask, filter or 3D transform. The referenced content is now painted
through the layer tree, the way &lt;code&gt;&amp;lt;mask&amp;gt;&lt;/code&gt;,&lt;code&gt;&amp;lt;clipPath&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; and
&lt;code&gt;&amp;lt;marker&amp;gt;&lt;/code&gt; content already is.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Made SVG &lt;code&gt;mask&lt;/code&gt; &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319390@main&quot;&gt;no longer force a
&lt;code&gt;RenderLayer&lt;/code&gt;&lt;/a&gt; in the Layer-Based SVG
Engine (LBSE), mirroring the &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318375@main&quot;&gt;earlier change for
&lt;code&gt;clip-path&lt;/code&gt;&lt;/a&gt;. A mask is now applied
during painting by &lt;code&gt;SVGNonLayerClippingAndMaskingScope&lt;/code&gt;, which opens one
transparency layer capturing the renderer's foreground and composites the mask
over it afterwards, and which also absorbed the clips that cannot be expressed
as a path. A container with a mask keeps its layer, since the mask covers its
whole subtree, while a leaf stays layer-free. This further reduces the layer
overhead that has been holding LBSE back against the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319306@main&quot;&gt;Skipped scroll coordination&lt;/a&gt; for
composited layers that have no scrolling role, where the per-layer update
previously walked every branch to detach roles the layer had never registered
for, only to hand back the parent node ID unchanged. Cutting that work out
shortens every compositing update, which matters for composition-heavy
workloads.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319284@main&quot;&gt;Fixed rendering of an outermost &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; with an empty
&lt;code&gt;viewBox&lt;/code&gt;&lt;/a&gt; in the Layer-Based SVG
Engine (LBSE), which per the &lt;a rel=&quot;external&quot; href=&quot;https://www.w3.org/TR/SVG2/coords.html#ViewBoxAttribute&quot;&gt;SVG
specification&lt;/a&gt; should
disable painting when the width or height is zero, matching what the legacy
engine already did.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319306@main&quot;&gt;Skipped scroll coordination work for layers that have no scrolling
role&lt;/a&gt; during compositing updates, where
&lt;code&gt;updateScrollCoordinationForLayer&lt;/code&gt; previously walked every branch to detach
roles the layer had never registered for, only to hand back the unchanged
parent node ID.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;releases-package&quot;&gt;Releases &#128230;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/08/19/webkitgtk2.52.6-released.html&quot;&gt;WebKitGTK
2.52.6&lt;/a&gt; and
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.52.6.html&quot;&gt;WPE WebKit 2.52.6&lt;/a&gt; have
been released, including a number of fixes for security issues covered in the
accompanying security advisory &lt;code&gt;WSA-2026-0005&lt;/code&gt;
(&lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/security/WSA-2026-0005.html&quot;&gt;GTK&lt;/a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/security/WSA-2026-0005.html&quot;&gt;WPE&lt;/a&gt;). It is recommended
for everybody to update to these stable releases.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Stabilization for the upcoming 2.54.x release series for both the GTK and WPE
ports is ongoing, with the first stable release, 2.54.0, expected around
mid-September 2026. In the meantime release candidates &lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/08/21/webkitgtk2.53.91-released.html&quot;&gt;WebKitGTK
2.53.91&lt;/a&gt; and
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.53.91.html&quot;&gt;WPE WebKit 2.53.91&lt;/a&gt; have
been released.&lt;/p&gt;
&lt;p&gt;Those interested in previewing the work done by the team in the last half year,
including the new Skia-based compositor that is expected to eventually replace
the aging TextureMapper, may want to give them a try and &lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org&quot;&gt;report any issues
found in Bugzilla&lt;/a&gt;.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 24 Aug 2026 23:30:34 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #73</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-73/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-73/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from August 10 to August 17.&lt;/p&gt;
&lt;p&gt;
Following an extra packed periodical, this week we get back to a more
regular pace with two nice bugfixes, and a new tool to analyze WebKit
performance on Linux!
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/pull/70333&quot;&gt;webkit-sysprof toolkit&lt;/a&gt; landed in &lt;code&gt;main&lt;/code&gt; thus introducing a set of tools for processing &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.gnome.org/GNOME/sysprof&quot;&gt;Sysprof&lt;/a&gt; &lt;code&gt;.syscap&lt;/code&gt; capture files recorded from WebKit (GTK/WPE ports). It extracts marks (timeline events) and counters (time-series metrics) from a capture and lets one dump, summarize, analyze, or plot delta-time histograms for them.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319121@main&quot;&gt;Fixed filters specified on the outermost &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element&lt;/a&gt; in the Layer-Based SVG Engine (LBSE), where a &lt;code&gt;filter: url(...)&lt;/code&gt; reference on an SVG root was silently dropped because the layer code skipped it, as the legacy engine used to apply it by itself. The filter region is now resolved against the SVG root's border box in its container's coordinate system, since the outermost &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; is a replaced element in the CSS box tree, not part of the SVG user space its children live in.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/319280@main&quot;&gt;Avoided serializing gradient and pattern transforms&lt;/a&gt; just to answer a presence check in the Layer-Based SVG Engine (LBSE). Asking &lt;code&gt;hasAttribute()&lt;/code&gt; whether &lt;code&gt;gradientTransform&lt;/code&gt; or &lt;code&gt;patternTransform&lt;/code&gt; was specified forced the transform list to be serialized into the attribute map whenever the base value was changed through the SVG DOM, even though that string is never read back, so the check is now answered directly from the typed accessor.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 17 Aug 2026 19:08:35 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #72</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-72/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-72/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from July 28 to August 10.&lt;/p&gt;
&lt;p&gt;
Quite a packed pair of weeks this time! The range of updates is big, but some
highlights are the handful of Layer-Based SVG Engine updates, performance
improvements, and the new WPE APIs. Finally, the Web Engines Hackfest
recordings are now published!
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/31a2484dd863a7a449323c3c222b47e028c2acf1&quot;&gt;Fixed&lt;/a&gt; &lt;code&gt;webkit_website_data_get_size()&lt;/code&gt; looking up sizes for localStorage, indexedDB, and the DOM Cache.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Enabled support for the &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/File_System_API&quot;&gt;File System&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Storage_API&quot;&gt;Storage&lt;/a&gt; APIs.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Added &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/bc363a82cf22f21fbe5472135e5bafc9b67b0bb3&quot;&gt;WEBKIT_WEBSITE_DATA_FILE_SYSTEM&lt;/a&gt; API to enable fetching/clearing File System data sites use.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;multimedia-movie-camera&quot;&gt;Multimedia &#127909;&lt;/h3&gt;
&lt;div class=&quot;wip-description&quot;&gt;
&lt;p&gt;GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.&lt;/p&gt;
&lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Landed a &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318708@main&quot;&gt;follow-up fix for the h264 edit list support&lt;/a&gt; to prevent regressions on YouTube MSE Conformance Tests 2019 when using older versions of GStreamer.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318859@main&quot;&gt;Avoided a spurious seek to zero&lt;/a&gt; when seeking to the end of an audio/video when playback starts.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318856@main&quot;&gt;Recovered a MotionMark compositing regression&lt;/a&gt; in the Skia backend, where respecting damage information during compositing cost about 20% on the composition suite and more than 50% on two of its tests. Restricting a draw to the damaged area means splitting it into source-rect-to-destination-rect pieces or drawing it under a device-space clip, and neither is needed when the damage already covers the whole draw, which is the common case in those tests because a composited layer is much smaller than a damage grid cell. Those draws are now issued exactly as they would be with damage turned off, avoiding a clip path that flushed the image set batch and left it an order of magnitude smaller, and with the regressions gone, using damage information for compositing was &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318857@main&quot;&gt;enabled again&lt;/a&gt; along with unifying damaged regions that are sent to the system compositor.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318440@main&quot;&gt;Skipped a per-frame visual overflow recomputation&lt;/a&gt; in the container paint cull of the Layer-Based SVG Engine (LBSE). The cull used a cached overflow rect that was recomputed by unioning all descendant bounds on a miss, which happened every frame for containers with an animated transform. It now only runs when the rect is already cached.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318410@main&quot;&gt;Skipped the outline paint pass&lt;/a&gt; for SVG renderers without an &lt;code&gt;outline&lt;/code&gt; in the Layer-Based SVG Engine (LBSE). Every shape used to be painted twice per frame, the second pass being a no-op in the common outline-free case, so guarding it behind &lt;code&gt;hasOutline()&lt;/code&gt; removes a redundant traversal from every frame.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318816@main&quot;&gt;Fixed masked SVG content being cut off&lt;/a&gt; at the edges in the Layer-Based SVG Engine (LBSE), where the mask image was sized over the enclosing integer rect of the mask content bounds in device space while the transparency layer clip was computed differently, losing the outermost pixels. An SVG renderer that is a box (&lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;foreignObject&amp;gt;&lt;/code&gt;) also used the CSS mask clip rect derived from the border box, which leaves out SVG content spilling outside it, and now uses the visual overflow rect instead&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318817@main&quot;&gt;Fixed most of the remaining &lt;code&gt;&amp;lt;mask&amp;gt;&lt;/code&gt; issues&lt;/a&gt; in the Layer-Based SVG Engine (LBSE): masks were displaced on targets whose children carry transforms, the mask region given by &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; was ignored so content reaching past it was not cut off, and the cached mask image was never dropped on layout, leaving a resized viewport masking with an image rasterized for the old size.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318873@main&quot;&gt;Stopped rebuilding &lt;code&gt;objectBoundingBox&lt;/code&gt; gradients&lt;/a&gt; on every layout size change in the Layer-Based SVG Engine (LBSE), which used to discard the cached gradient and re-collect its attributes (serializing every animated property back to a string, including &lt;code&gt;gradientTransform&lt;/code&gt;) on the next paint. That work is wasted for &lt;code&gt;objectBoundingBox&lt;/code&gt; units, whose coordinates resolve against the object bounding box with the userspace transform recomputed on every paint anyway, so only the clients are repainted now, while &lt;code&gt;userSpaceOnUse&lt;/code&gt; gradients resolve against the viewport and are still invalidated as before.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318882@main&quot;&gt;Cached the SVG fill and stroke paint server directly on the renderer&lt;/a&gt; in the Layer-Based SVG Engine (LBSE), instead of in the shared referenced-resources table living in a renderer's rar data, where every fill and every stroke paid the cost of a hash map lookup just to reach the cache, which gives a small win on the MotionMark/Suits performance test. It also fixed a shape referencing a paint server that does not exist yet, which kept painting unfilled once an element finally took that id, because the shape registered itself as a pending resource under the full resolved URL while the lookups used the bare fragment identifier.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318411@main&quot;&gt;Sped up mapping the paint dirty rect&lt;/a&gt; through transforms in the Layer-Based SVG Engine (LBSE). Transformed SVG paints inverted the full 4x4 matrix on every paint, and now use the cheaper inverse of the 2x3 affine transform whenever the transform is affine, falling back to the 4x4 inverse only for 3D transforms.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Made SVG &lt;code&gt;clip-path&lt;/code&gt; no longer force a &lt;code&gt;RenderLayer&lt;/code&gt; in the Layer-Based SVG Engine (LBSE). A bare clip is now applied during painting through a shared &lt;code&gt;ClipPathPaintScope&lt;/code&gt;, a scope object that sets up the clip in its constructor and tears it down afterwards, handling CSS basic-shape and box clips as well as SVG clipper resources so both regular CSS boxes and SVG content share one path. This is a further step in &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318375@main&quot;&gt;removing the intrinsic need for layers&lt;/a&gt; on SVG renderers, continuing the effort to close the performance gap between LBSE and the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318669@main&quot;&gt;Fixed dynamic &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; updates&lt;/a&gt; on SVG &lt;code&gt;&amp;lt;foreignObject&amp;gt;&lt;/code&gt; elements, which stopped taking effect after the viewport geometry started being derived from the resolved style. The &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes are presentation attributes mapped to the CSS &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; properties, but only &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; marked the presentational hint style as dirty when they changed, so a style recalc never ran for &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; and layout kept reading stale values. All four geometry attributes now invalidate the presentational hint style, matching how &lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; handles its geometry, so setting &lt;code&gt;x.baseVal.value&lt;/code&gt; from script repositions the &lt;code&gt;&amp;lt;foreignObject&amp;gt;&lt;/code&gt; as expected.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318412@main&quot;&gt;Added support for external and &lt;code&gt;data:&lt;/code&gt; URL references&lt;/a&gt; to &lt;code&gt;clip-path&lt;/code&gt;, markers and paint servers (gradients and patterns) in the Layer-Based SVG Engine (LBSE). Until now the LBSE resource resolvers only looked for the referenced fragment inside the local document, so markup like &lt;code&gt;url(file.svg#id)&lt;/code&gt; silently resolved to nothing, while filters already worked and the legacy SVG engine handled all of these since a few weeks.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/318751@main&quot;&gt;Fixed SVG filters vanishing&lt;/a&gt; on elements with a very large bounding box in the Layer-Based SVG Engine (LBSE). The filter region was seeded with the element's object bounding box and then united with each referenced &lt;code&gt;&amp;lt;filter&amp;gt;&lt;/code&gt; region, but a referenced &lt;code&gt;&amp;lt;filter&amp;gt;&lt;/code&gt; brings its own region, and that region alone decides where the filter paints, so the union could grow far past the image buffer limits and get clamped down to scale that made the output disappear. When every function in the chain is a &lt;code&gt;&amp;lt;filter&amp;gt;&lt;/code&gt; reference the bounding box is now dropped and only the referenced regions are kept, matching what the legacy SVG engine does, while &lt;code&gt;objectBoundingBox&lt;/code&gt; filter units still resolve exactly as before and HTML/CSS filters are untouched.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;wpe-webkit-pager&quot;&gt;WPE WebKit &#128223;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/0496fa627ebfc60e411c0a52009387ca10b4e584&quot;&gt;Add&lt;/a&gt; the &lt;code&gt;WebView::run-color-chooser&lt;/code&gt; API to WPE to allow applications to show color choosers, similar to WebKitGTK's API.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The WPE port can now &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317752@main&quot;&gt;use libsecret for persistent credential storage&lt;/a&gt;, reusing the implementation from the WebKitGTK port. This is disabled by default and can be toggled passing &lt;code&gt;-DUSE_LIBSECRET=ON&lt;/code&gt; to CMake when configuring the build.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/062e3932bff008ef3a6c1069e561b372ad534547&quot;&gt;Add&lt;/a&gt; the &lt;code&gt;WebKitClipboardPermissionRequest&lt;/code&gt; API to WPE, allowing support for the clipboard permission similar to WebKItGTK.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;community-events-handshake&quot;&gt;Community &amp;amp; Events &#129309;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The videos of the &lt;a rel=&quot;external&quot; href=&quot;https://webengineshackfest.org/&quot;&gt;Web Engines Hackfest&lt;/a&gt; 2026 talks have been &lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/playlist?list=PL4sEzdAGvRgDkOXbVAbnOWCaIOV_evSfo&quot;&gt;published&lt;/a&gt;, including the sessions from the new WPE WebKit track. This year the following WebKit-related talks have been recorded:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=-68_9Sg2VWk&quot;&gt;From libwpe to WPEPlatform: Building Embedded Browser on RPi with New WPE API&lt;/a&gt;, by Kate Lee, about new embedding API that is planned to be deemed stable for the 2.54 release series.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=qVc0I1Z1ZKU&quot;&gt;Refactoring composition in WPE with Skia&lt;/a&gt;, by Carlos Garc&#237;a Campos, about the new Skia-based compositor currently in development that has been recently featured in our weekly dispatches.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=W2pfbFeV1Pk&quot;&gt;Techniques for reducing GPU usage in WPE&lt;/a&gt;, by  Pawe&#322; Lampe, which is exactly what reads in the tin and how to balance CPU and GPU usage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=rX6y219m3OU&quot;&gt;Speeding up WPEWebKit and WebKitGTK with Profile-Guided Optimization&lt;/a&gt;, by Lauro Moura, because everybody likes to squeeze performance out of an existing codebase without rewriting it thanks to compiler techniques.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=dnZ4jNKZzcY&quot;&gt;No QA, No WPE: Catch Regressions Before You Do&lt;/a&gt;, by Claudio Saavedra and Nikolas Zimmermann, about how continuous integration and quality assurance has been improved (and continues to) to improve stability and performance in the GTK and WPE WebKit ports.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.youtube.com/watch?v=f6fM0B0kcPk&quot;&gt;WPEPlatform API for Android&lt;/a&gt;, by Alejandro G. Castro, which is not only this year's update on WPE Android but also covers how the platform-dependent components have been partially rewritten and migrated to the WPEPlatform API.&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;


&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 10 Aug 2026 18:51:04 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #71</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-71/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-71/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from July 14 to July 27.&lt;/p&gt;
&lt;p&gt;
This two-week update includes plenty of changes to the Skia compositor,
changes to multimedia support, three blog posts, and assorted improvements.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The Web Inspector &#8220;Layout &amp;amp; Rendering&#8221; timeline &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317302@main&quot;&gt;now shows a &lt;code&gt;Layout Invalidated&lt;/code&gt; event for &lt;em&gt;every&lt;/em&gt; element&lt;/a&gt;
that needs relayout, not just the layout root (with the old root-only event
renamed to &lt;code&gt;Layout Scheduled&lt;/code&gt;). This unveils why some layouts take much longer
than others. No more guessing which of dozens of nodes is actually to blame!&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The &lt;code&gt;webkit://gpu&lt;/code&gt; page has &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317610@main&quot;&gt;gained a dark
style&lt;/a&gt;, which will be used when the
system settings indicate that dark mode is preferred by the user.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;multimedia-movie-camera&quot;&gt;Multimedia &#127909;&lt;/h3&gt;
&lt;div class=&quot;wip-description&quot;&gt;
&lt;p&gt;GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.&lt;/p&gt;
&lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The experimental GstWebRTC backend was
&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317849@main&quot;&gt;removed&lt;/a&gt; and &lt;em&gt;libwebrtc&lt;/em&gt; usage was
&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317767@main&quot;&gt;enabled&lt;/a&gt; in the &lt;code&gt;main&lt;/code&gt; branch. We hope
to enable WebRTC support by default in the 2.56 series, scheduled around March
2027.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317765@main&quot;&gt;MP4 edit lists support&lt;/a&gt; was enabled in
the MSE backend, improving timestamp accuracy, specially when handling of
B-frames.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317256@main&quot;&gt;Split the compositing walk&lt;/a&gt; in the
Skia compositor into a damage pass and a paint pass, so the frame damage is
known before the first draw. The damage pass walks the layer tree with a
&lt;code&gt;SkNoDrawCanvas&lt;/code&gt; in place of the real canvas, so every draw is discarded and
only the damage is collected. Both passes run from a single &lt;code&gt;paint()&lt;/code&gt; that
applies animations and computes the transforms once, so the two see the same
tree. Knowing the damage up front is what lets the compositor eventually paint
only the parts of a frame that actually changed.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317400@main&quot;&gt;Wired up damage-driven compositing&lt;/a&gt; on
the Skia compositor, so a frame re-composites only the region that actually
changed instead of the whole surface, when the
&lt;code&gt;UseDamagingInformationForCompositing&lt;/code&gt; feature is enabled (not yet on by
default). Each frame's damage is combined with what each swap-chain target
still needs to redraw since it was last drawn into, and the clear and every
draw are clipped to that region, which is a milestone towards no longer
repainting untouched pixels every frame.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Made the root layer &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317343@main&quot;&gt;collect the frame damage
itself&lt;/a&gt; in the Skia compositor, instead
of having each layer report its own changes. Reporting leaves a gap whenever a
layer is in no position to report, e.g. a destroyed one took its painted rectangle
with it, so what it had drawn stayed on screen. The root now holds one rectangle per
layer and compares it against what each frame's walk finds, so a layer that
moved is repainted in both places, and a layer the walk never reaches is
repainted where it used to be and dropped. Nothing has to notice anything for
the pixels it left behind to be repainted, which is what makes it safe to
restrict composition to the damaged region by default in future commits.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317387@main&quot;&gt;Limited every content draw to the target's repaint
region&lt;/a&gt; in the Skia compositor, so a
composited frame can redraw only the pixels that actually changed. Each content
type restricts itself to the region's rectangles rather than clipping the
canvas, since a multi-rectangle clip cannot be a hardware scissor and would make
Skia build a mask and break batching. This is the groundwork for damage-driven
compositing, which stays off by default behind the damage-tracking feature
flag, as the compositor still passes no region and nothing is restricted yet.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Made each swap-chain target &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317342@main&quot;&gt;track its own
damage&lt;/a&gt; since it was last current.
Repainting only what changed is correct only when drawing into the target that
holds the previous frame, but the swap chain hands back whichever target is
free, and that one is a frame or more behind. Each frame's damage is now added
to every target as it is recorded and cleared from a target when that target is
presented, instead of being built as a side effect of reading it.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Taught the tile and image draws in the Skia compositor to &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317247@main&quot;&gt;split themselves by
damage rectangle&lt;/a&gt;, so a frame only repaints
the parts of a layer that actually changed. A new &lt;code&gt;SkiaDamageRegion&lt;/code&gt; holds the
frame's damage in device space and is built once per frame, and each draw is
restricted to it: skipped when it touches no damage, split into one sub-draw
per damage rectangle it overlaps, or drawn under a device-space clip when a rotated
or skewed transform rules out working with rectangles. Nothing feeds a damage region
in yet, so every draw still paints in full&#8212;this prepares for future patches
enabling using damage information in the composition&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317142@main&quot;&gt;Fixed missing repaints&lt;/a&gt; when
compositor-applied layer state changes dynamically in the Coordinated Graphics
backend. A layer recorded damage when its backing store re-rendered or a new
contents buffer arrived, but the compositor also handles filters, masks, clip
path changes, the contents rectangle, the contents tiling, the blend mode and
contents visibility, and changing any of those alters the pixels it produces
without dirtying a tile. Those setters now damage the whole layer, so a
compositor that repaints only the damaged rectangles no longer leaves the previous
frame's pixels on screen.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;community-events-handshake&quot;&gt;Community &amp;amp; Events &#129309;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Nikolas Zimmermann has written a two-part blog series about the current the new
Layer-Based SVG Engine (LBSE), with the first post covering &lt;a rel=&quot;external&quot; href=&quot;https://blogs.igalia.com/nzimmermann/posts/2026-07-14-lbse-conditional-layers/&quot;&gt;the effort to
reduce layer
overhead&lt;/a&gt;
using layers conditionally, and the second about &lt;a rel=&quot;external&quot; href=&quot;https://blogs.igalia.com/nzimmermann/posts/2026-07-22-lbse-paint-order-segments/&quot;&gt;how compositing is being
implemented&lt;/a&gt;
and the complications introduced due to paint ordering rules.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Lo&#239;c Le Page has published a &lt;a rel=&quot;external&quot; href=&quot;https://blogs.igalia.com/llepage/the-wpe-platform-api/&quot;&gt;blog
post&lt;/a&gt; explaining how to
use the new &lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/reference/2.53.3/wpe-platform-2.0/&quot;&gt;WPEPlatform
API&lt;/a&gt; to implement a
custom WPE integration. While presented example uses
&lt;a rel=&quot;external&quot; href=&quot;https://www.glfw.org/&quot;&gt;GLFW&lt;/a&gt; and EGL to show Web content on an X11 window, the
concepts are useful for anyone looking into embedding WPE.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Tue, 28 Jul 2026 01:04:26 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Nikolas Zimmermann: Implementing compositing in LBSE</title>
	<guid>https://blogs.igalia.com/nzimmermann/posts/2026-07-22-lbse-paint-order-segments/</guid>
	<link>https://blogs.igalia.com/nzimmermann/posts/2026-07-22-lbse-paint-order-segments/</link>
	<description>
Keeping paint order correct with paint order segments        </description>
	<pubDate>Wed, 22 Jul 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Nikolas Zimmermann: Reducing layer overhead in LBSE</title>
	<guid>https://blogs.igalia.com/nzimmermann/posts/2026-07-14-lbse-conditional-layers/</guid>
	<link>https://blogs.igalia.com/nzimmermann/posts/2026-07-14-lbse-conditional-layers/</link>
	<description>
Conditional layer creation in the layer based SVG engine        </description>
	<pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #70</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-70/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-70/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from June 30 to July 13.&lt;/p&gt;
&lt;p&gt;
The summer continues with many updates to the new SVG engine (LBSE),
improvements to the new Skia-based compositor, some small API additions,
and ever-important stable releases with security fixes.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316680@main&quot;&gt;Enabled&lt;/a&gt; the &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/CloseWatcher&quot;&gt;CloseWatcher
API&lt;/a&gt; and
dialog's &lt;code&gt;closedby&lt;/code&gt; attribute in stable.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;New API &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316808@main&quot;&gt;has been added&lt;/a&gt; which allows
specifying per-navigation &lt;code&gt;User-Agent&lt;/code&gt; string values using
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/reference/stable/wpe-webkit-2.0/method.PolicyDecision.use_with_policies.html&quot;&gt;webkit_policy_decision_use_with_policies()&lt;/a&gt;.
Applications now have more
granularity to decide which &lt;code&gt;User-Agent&lt;/code&gt; websites are presented with,
complementing the existing global
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/reference/stable/wpe-webkit-2.0/property.Settings.user-agent.html&quot;&gt;WebKitSettings:user-agent&lt;/a&gt;
setting.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Roughly &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316833@main&quot;&gt;halved the cost of the Skia based
compositor&lt;/a&gt; on WPE running on Vivante
GPUs with the Etnaviv driver, by turning off Skia's mipmap sharpening option.
That option is enabled by default and makes the Skia shader generator append a
small negative level-of-detail (LOD) bias to every mipmap-capable texture
sample.  WPE does not use mipmapping at all, so the bias sharpened nothing,
but it still turned each texture fetch into a LOD lookup, which is a slow path
on the tiled GPUs found in the i.MX series. Disabling it restores usage of
faster, plain fetch operations.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316716@main&quot;&gt;Fixed broken rendering with the Skia
compositor&lt;/a&gt; on WPE when super-tiled
textures are enabled on Vivante GPUs. Those tile buffers are allocated padded
up to a multiple of 64 pixels, so the physical texture is larger than the
logical tile, but the Skia backing failed to take this difference into
account, leading to distorted tile images being rendered.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316881@main&quot;&gt;Stopped the Skia compositor from blending opaque
layers&lt;/a&gt; on WPE. Every layer was drawn
with the default source-over blend mode, which leaves GPU blending switched on
even for fully opaque layers that do not need it, so the cost was paid on
every composited frame.&lt;/p&gt;
&lt;p&gt;Layers that are opaque, drawn at full opacity and using the default blend mode
are now composited with a plain source blend mode instead, which lets Skia
turn blending off and lowers GPU bandwidth usage, benefiting tiled GPUs the
most.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316543@main&quot;&gt;Cached the concatenated SVG &lt;code&gt;transform&lt;/code&gt; attribute
matrix&lt;/a&gt; on graphics elements in the
Layer-Based SVG Engine (LBSE).&lt;/p&gt;
&lt;p&gt;Reading the &lt;code&gt;transform&lt;/code&gt; attribute walked the whole transform list and
multiplied every item together again, and that happened around three times per
animation frame for each element, even though the result only changes when the
transform list itself is mutated.&lt;/p&gt;
&lt;p&gt;The concatenated matrix is now stored on the element and invalidated whenever
a transform-related attribute changes, so the multiplication runs once per
mutation instead of once per read. This cuts repeated matrix work out of the
per-frame path for animated SVG content.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317036@main&quot;&gt;Moved the clip out of the SVG child-paint
loop&lt;/a&gt; in the Layer-Based SVG Engine
(LBSE).&lt;/p&gt;
&lt;p&gt;Painting a container used to set up a clip rectangle for every child shape in
turn, so each shape did its own graphics-context save, clip and restore even
though the clip rectangle was identical for all of them. When there is a
single region to clip to and no child paints into its own layer, that clip is
now established once and shared by every child, transformed or not.&lt;/p&gt;
&lt;p&gt;This removes a per-shape save and clip from the hot painting path of SVG
documents with many children.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/317077@main&quot;&gt;Cached the SVG transform origin&lt;/a&gt; on
SVG renderers in the Layer-Based SVG Engine (LBSE).&lt;/p&gt;
&lt;p&gt;Every transform flush recomputed the origin for each non-layered SVG shape,
even though it only depends on the &lt;code&gt;transform-origin&lt;/code&gt; style and the transform
reference box, and sampling MotionMark's Suits test at fixed complexity showed
that computation taking around 1% of the WebProcess main thread.&lt;/p&gt;
&lt;p&gt;The origin is now cached and keyed on the reference box, with a style change
to &lt;code&gt;transform-origin&lt;/code&gt; or &lt;code&gt;transform-box&lt;/code&gt; dropping the cache, and the fast path
is limited to plain SVG transforms so viewport containers and CSS-transformed
renderers keep computing it directly. This removes a repeated per-shape cost
from animated SVG content, and the caching scope can be widened later.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316545@main&quot;&gt;Cached the SVG viewport size&lt;/a&gt; used to
resolve the transform reference box in the Layer-Based SVG Engine (LBSE).&lt;/p&gt;
&lt;p&gt;The default &lt;code&gt;transform-box&lt;/code&gt; for SVG is &lt;code&gt;view-box&lt;/code&gt;, so every transformed shape
resolved the viewport from the SVG root's content box again on each query,
both when updating its local transform and again during paint. The viewport is
constant after layout, so it is now cached on the &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; element and only
recomputed when layout actually changes it, on resize, zoom or a &lt;code&gt;viewBox&lt;/code&gt;
update. This removes another repeated per-frame computation from the transform
path for animated SVG content.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316880@main&quot;&gt;Coalesced the SVG transform flush&lt;/a&gt;
into one minimal repaint per container in the Layer-Based SVG Engine (LBSE).&lt;/p&gt;
&lt;p&gt;Once per rendering update WebKit processes every SVG renderer whose transform
changed, whether from script or an animation, and that repaint pass was the
dominant per-frame cost on MotionMark's Suits subtest. Instead of walking each
moved renderer up to its repaint container, the flush now computes each
child's rectangle in its parent's coordinate space, unions the children per
parent, maps that single union up the chain once, and issues one
&lt;code&gt;repaintUsingContainer()&lt;/code&gt; call per repaint container rather than one per
shape.&lt;/p&gt;
&lt;p&gt;This also stops requesting outline bounds, which for SVG merely duplicated the
visual overflow rectangle, and refreshes the bounding-box and visual-overflow
caches that a layout would normally update, so &lt;code&gt;getBBox()&lt;/code&gt; and paint or
hit-test culling never read a stale rectangle. This collapses many
backing-store invalidations into one while keeping the repainted region
minimal, closing the performance gap to the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316544@main&quot;&gt;Avoided re-resolving the SVG transform from style on every
paint&lt;/a&gt; in the Layer-Based SVG Engine
(LBSE).&lt;/p&gt;
&lt;p&gt;Non-layer SVG renderers already cache their transform in &lt;code&gt;m_localTransform&lt;/code&gt;,
but the painting code path used to recompute it from scratch each time,
concatenating the &lt;code&gt;transform&lt;/code&gt; list, applying &lt;code&gt;transform-origin&lt;/code&gt; and
multiplying matrices, only because the cached value uses a different transform
origin. The paint transform is now derived directly from the cached one by
translating around the nominal origin, which removes that per-paint
recomputation and cuts the cost of painting transformed SVG content.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316702@main&quot;&gt;Fixed a repaint bug&lt;/a&gt; in the
Layer-Based SVG Engine (LBSE) where dynamically changing a marker's
&lt;code&gt;markerUnits&lt;/code&gt; or &lt;code&gt;orient&lt;/code&gt; attribute left stale pixels behind. Such a change
resizes every shape that references the marker, but a referencing shape
without a layer gets no post-layout position update, so only its new bounds
were repainted&#8212;a shrinking marker left its former area on screen.&lt;/p&gt;
&lt;p&gt;The visual overflow rectangle, markers included, is now cached at the end of
shape layout while the geometry is still current, so a marker change can
repaint the old bounds before recomputing the new ones. The extra repaint is
limited to markers, since gradients and patterns do not affect a client's
bounds, and the resulting repaint rects are more accurate than the legacy SVG
engine's.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;wpe-webkit-pager&quot;&gt;WPE WebKit &#128223;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Added a &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/316840@main&quot;&gt;new feature flag&lt;/a&gt;,
&lt;code&gt;BackForwardCacheWithMedia&lt;/code&gt;, which may be used to disable storing pages with
media content in the back-forward cache. This should solve the problem with
hardware decoders kept occupied on low-end devices in case of caching pages
with media after navigation.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;releases-package&quot;&gt;Releases &#128230;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/07/09/webkitgtk2.52.5-released.html&quot;&gt;WebKitGTK 2.52.5&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.52.5.html&quot;&gt;WPE WebKit 2.52.5&lt;/a&gt; have been released, including a number of fixes for security issues, and therefore it is recommended to update. An accompanying security advisory will be published in the coming days. Additionally, these releases include small improvements and Web compatibility improvements.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 13 Jul 2026 22:59:14 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #69</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-69/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-69/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from June 22 to June 29.&lt;/p&gt;
&lt;p&gt;
After a small break after the Web Engines Hackgest, we're back with another
round of updates, this time with a couple of exciting improvements to the
SVG engine, a WebRTC fix, and support for WebP images with the toDataURL()
API.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Made RenderLayer creation &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315610@main&quot;&gt;conditional&lt;/a&gt; for SVG renderers in the new Layer-Based SVG Engine (LBSE), so a layer is now only created when one is actually needed for intrinsic reasons (3D transforms, opacity, etc.) instead of unconditionally for every renderer. Plain 2D transforms no longer force a layer and are applied directly during painting. This is the groundwork for follow-up patches that remove the intrinsic need for layers when applying clipping, masking and filters to SVG subtrees. It is an important milestone towards reducing the overhead that has been holding back LBSE performance compared to the legacy SVG engine.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315674@main&quot;&gt;Fixed the paint order&lt;/a&gt; of non-composited children around composited SVG siblings  in the Layer-Based SVG Engine (LBSE). A layered container paints its children from a single flat list in DOM (and SVG paint) order, but some children are composited into their own GraphicsLayer for reasons like &lt;code&gt;will-change&lt;/code&gt;, a 3D transform or certain &lt;code&gt;opacity&lt;/code&gt; cases. The flat child list is now split into contiguous paint-order segments at those boundaries, with each run of plain children painted by its own overlay layer placed at the correct depth in the compositor's child list. This keeps every child in its DOM order without giving trailing siblings a RenderLayer or backing store of their own, and a container with no composited children produces no segments at all, so the common case costs nothing. This allows us to support composition within LBSE subtrees in a performant way, after dropping the requirement that every renderer creates a layer.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;multimedia-movie-camera&quot;&gt;Multimedia &#127909;&lt;/h3&gt;
&lt;div class=&quot;wip-description&quot;&gt;
&lt;p&gt;GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.&lt;/p&gt;
&lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Fixed &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315815@main&quot;&gt;initial decoding issues&lt;/a&gt; on LibWebRTC on platforms that do video decoding on the final playback stage (for efficiency and performance), instead of on the LibWebRTC decoder component.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315446@main&quot;&gt;Added support for producing WebP images&lt;/a&gt; with canvas' &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL&quot;&gt;.toDataURL()&lt;/a&gt;. Using &lt;code&gt;1.0&lt;/code&gt; as the quality setting will &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315446@main&quot;&gt;produce lossless images&lt;/a&gt;, which matches the behaviour of Chromium and Firefox.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 29 Jun 2026 21:00:20 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #68</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-68/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-68/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from June 9 to June 16.&lt;/p&gt;
&lt;p&gt;
The major highlight this week is the Web Engines Hackfest! Despite it, there
are a variety of updates as well, such as various improvements to input
handling in WPE WebKit and WebKitGTK, WPE menu rendering changes, and a
plethora of other smaller improvements.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Input methods may now &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315091@main&quot;&gt;know whether a field is intended to be used as search input&lt;/a&gt;, in which case the &lt;code&gt;WebKitInputMethodContext:input-purpose&lt;/code&gt; property will have the value &lt;code&gt;WEBKIT_INPUT_PURPOSE_SEARCH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Due to GTK not providing an equivalent value for &lt;code&gt;GtkInputPurpose&lt;/code&gt;, the default behaviour is to continue mapping search fields to &lt;code&gt;GTK_INPUT_PURPOSE_FREE_FORM&lt;/code&gt; as before; but custom input methods may use the new value to detect search inputs. When using WPEPlatform, the value is mapped to &lt;code&gt;WPE_INPUT_PURPOSE_SEARCH&lt;/code&gt;, which has been added as well.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314898@main&quot;&gt;Handle&lt;/a&gt; selections as part of &lt;code&gt;moveBefore&lt;/code&gt;.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314884@main&quot;&gt;Corrected&lt;/a&gt; user activation propagation for close watchers.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314695@main&quot;&gt;Invalidate&lt;/a&gt; &lt;code&gt;:lang()&lt;/code&gt; and &lt;code&gt;:dir()&lt;/code&gt; selectors after &lt;code&gt;moveBefore&lt;/code&gt;.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/315081@main&quot;&gt;Enable&lt;/a&gt; Close Watchers in preview.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;wpe-webkit-pager&quot;&gt;WPE WebKit &#128223;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;WPE &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/5ccb692f3e65ac32d6d6b83796dd8c9ca0bf1e1b&quot;&gt;now&lt;/a&gt; renders its own popup menus for elements such as &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/select&quot;&gt;&lt;code&gt;select&lt;/code&gt;&lt;/a&gt;. It supports all styling options the web provides such as colors and fonts. The internal menu can be overriden with the existing &lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/reference/stable/wpe-webkit-2.0/signal.WebView.show-option-menu.html&quot;&gt;&lt;code&gt;WebView::show-option-menu&lt;/code&gt;&lt;/a&gt; signal. Cog for example still renders its own (with a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Igalia/cog/commit/8a7051b553328638772188f617e1e05e7a5ca486&quot;&gt;recent commit&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/webkit/blog/2026/wip-68/context-menu-1.png&quot; alt=&quot;A colorful context menu&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/webkit/blog/2026/wip-68/context-menu-2.png&quot; alt=&quot;A context menu with a simpler style&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/webkit/blog/2026/wip-68/context-menu-iframe.png&quot; alt=&quot;A context menu inside an iFrame&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blogs.igalia.com/webkit/blog/2026/wip-68/context-menu-rotated.png&quot; alt=&quot;A context menu inside a rotated container&quot; /&gt;&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;community-events-handshake&quot;&gt;Community &amp;amp; Events &#129309;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https://webengineshackfest.org/&quot;&gt;Web Engines Hackfest&lt;/a&gt; started! We had a fantastic first day of talks, and now are heading to &lt;a rel=&quot;external&quot; href=&quot;https://webengineshackfest.org/#breakout-sessions&quot;&gt;breakout sessions&lt;/a&gt;. Make sure to check the schedule for sessions that may interest you!&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Tue, 16 Jun 2026 10:14:06 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #67</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-67/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-67/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from June 1 to June 8.&lt;/p&gt;
&lt;p&gt;
Another great week, this time we have a performance improvement implemented
in the Skia-based compositor, an excellent writeup about how to investigate
and isolate memory leaks in WPE WebKit, a couple of multimedia fixes, and a
variety of improvements and fixes across WebKit ports.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313910@main&quot;&gt;Implement&lt;/a&gt; dialog integration with close watcher.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314384@main&quot;&gt;Implement&lt;/a&gt; node iterator and live range pre-remove steps for in-progress &lt;code&gt;moveBefore()&lt;/code&gt; implementation.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313888@main&quot;&gt;Fix&lt;/a&gt; an early return in CloseWatcher close to align with the spec.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The Web Inspector &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/commit/f7dd925a68af3c39406f6942a728e1428d00f802&quot;&gt;now shows&lt;/a&gt; DOM nodes associated with layout and rendering events in a separate column of layout timeline next to initiator, sizing, and timing information. Hovering over rows in the details table highlights the associated node, and clicking it reveals the node in the &quot;Elements&quot; tab. This makes it easier to match events with specific nodes and helps debugging changes to a web page.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314400@main&quot;&gt;Fix&lt;/a&gt; popover light dismiss to account for disabled command buttons.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;multimedia-movie-camera&quot;&gt;Multimedia &#127909;&lt;/h3&gt;
&lt;div class=&quot;wip-description&quot;&gt;
&lt;p&gt;GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.&lt;/p&gt;
&lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=316190&quot;&gt;Fix&lt;/a&gt; &lt;code&gt;mediaTime&lt;/code&gt; provided with &lt;code&gt;requestVideoFrameCallback&lt;/code&gt; in case of captureCanvas as source.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org/show_bug.cgi?id=316404&quot;&gt;Don't use the Rialto specific video decoder+sink on WebAudio, where its usage as a pure decoder isn't compatible&lt;/a&gt; and would cause issues.&lt;/p&gt;
  &lt;/div&gt;
&lt;h3 id=&quot;graphics-frame-photo&quot;&gt;Graphics &#128444;&#65039;&lt;/h3&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/314626@main&quot;&gt;Batched painting&lt;/a&gt; support was implemented in the Skia-based compositor, improving the performance in several cases.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;community-events-handshake&quot;&gt;Community &amp;amp; Events &#129309;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Pawel Lampe published &lt;a rel=&quot;external&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;a blog post&lt;/a&gt; where he's presenting and discussing a guide on structured approach to narrowing down and debugging memory leaks within WPE WebKit.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Mon, 08 Jun 2026 20:57:00 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Igalia WebKit Team: WebKit Igalia Periodical #66</title>
	<guid>https://blogs.igalia.com/webkit/blog/2026/wip-66/</guid>
	<link>https://blogs.igalia.com/webkit/blog/2026/wip-66/</link>
	<description>
&lt;p&gt;Update on what happened in WebKit in the week from May 19 to June 1.&lt;/p&gt;
&lt;p&gt;
The main feature of this week are new releases: stable ones with many security
fixes, and development ones with the new Skia-based compositor enabled. Additionally,
there was work on Web-facing features, optimizations, spell checking support for
the WPE port, and more.
&lt;/p&gt;
&lt;h2 id=&quot;cross-port-cat&quot;&gt;Cross-Port &#128049;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;WebKit now &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/pull/63123&quot;&gt;supports&lt;/a&gt; mirroring
MathML stretchy operators using the OpenType &lt;code&gt;rtlm&lt;/code&gt; feature.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313671@main&quot;&gt;Replaced&lt;/a&gt; the &lt;code&gt;CloseWatcherManager&lt;/code&gt;'s
&lt;code&gt;escapeKeyHandler&lt;/code&gt;, which will allow other types of close signals to be supported.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313611@main&quot;&gt;Implemented&lt;/a&gt; queuing mutation observer
records in the work-in-progress &lt;code&gt;moveBefore()&lt;/code&gt; implementation.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313838@main&quot;&gt;Implemented&lt;/a&gt; popover integration with
close watcher.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313840@main&quot;&gt;Fixed&lt;/a&gt; popover light dismiss to
account for &lt;code&gt;popovertarget&lt;/code&gt; on input buttons.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Content filters now &lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313681@main&quot;&gt;create temporary files in the compiled filters
directory&lt;/a&gt;, which ensures that a file
rename can always be used to place them at their final location. This avoids
falling back to a regular file copy, which can be slower, when the temporary
directory returned by &lt;code&gt;g_get_tmp_dir()&lt;/code&gt; (typically &lt;code&gt;/tmp&lt;/code&gt;) is in a different
volume than the filters' storage path configured for
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/reference/stable/wpe-webkit-2.0/class.UserContentFilterStore.html&quot;&gt;WebKitUserContentFilterStore&lt;/a&gt;.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;wpe-webkit-pager&quot;&gt;WPE WebKit &#128223;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://commits.webkit.org/313825@main&quot;&gt;Enabled spell checking support in
WPE&lt;/a&gt;. The existing implementation for
the WebKitGTK port, which uses the
&lt;a rel=&quot;external&quot; href=&quot;https://rrthomas.github.io/enchant/&quot;&gt;Enchant&lt;/a&gt; library as a backend, was
generalized to provide spell checking support in WPE as well. The feature may
be toggled at build time using the &lt;code&gt;ENABLE_SPELLCHECK&lt;/code&gt; CMake option.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;releases-package&quot;&gt;Releases &#128230;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/06/02/webkitgtk2.52.4-released.html&quot;&gt;WebKitGTK
2.52.4&lt;/a&gt; and
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.52.4.html&quot;&gt;WPE WebKit 2.52.4&lt;/a&gt; have
been released; they include a number of fixes for security issues, and it is a
highly recommended update. The corresponding security advisory, &lt;code&gt;WSA-2026-0003&lt;/code&gt;
(&lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/security/WSA-2026-0003.html&quot;&gt;GTK&lt;/a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/security/WSA-2026-0003.html&quot;&gt;WPE&lt;/a&gt; is available as well.
The release also includes a number of small improvements and Web compatibility
fixes.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;Additionally, development releases &lt;a rel=&quot;external&quot; href=&quot;https://webkitgtk.org/2026/05/28/webkitgtk2.53.3-released.html&quot;&gt;WebKitGTK
2.53.3&lt;/a&gt; and
&lt;a rel=&quot;external&quot; href=&quot;https://wpewebkit.org/release/wpewebkit-2.53.3.html&quot;&gt;WPE WebKit 2.53.3&lt;/a&gt; are
available since last week. These include a change to use a new Skia-based
compositor by default, which is intended to replace TextureMapper once ready.
Therefore, &lt;a rel=&quot;external&quot; href=&quot;https://bugs.webkit.org&quot;&gt;bug reports&lt;/a&gt; related to website rendering
are particularly welcome when using this and subsequent development releases.&lt;/p&gt;
  &lt;/div&gt;
&lt;h2 id=&quot;infrastructure-construction-site&quot;&gt;Infrastructure &#127959;&#65039;&lt;/h2&gt;
  &lt;div class=&quot;wip-item&quot;&gt;
&lt;p&gt;The deprecated and un-maintained Flatpak-based SDK was
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit/pull/61566&quot;&gt;removed&lt;/a&gt;. Developers working on
the WPE and GTK WebKit ports are encouraged to migrate to the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Igalia/webkit-container-sdk&quot;&gt;new
SDK&lt;/a&gt;.&lt;/p&gt;
  &lt;/div&gt;
&lt;div class=&quot;wip-end&quot;&gt;
&lt;p&gt;That&#8217;s all for this week!&lt;/p&gt;
&lt;/div&gt;        </description>
	<pubDate>Tue, 02 Jun 2026 00:12:49 +0000</pubDate>
	<dc:creator>Igalia WebKit Team</dc:creator>
</item>
<item>
	<title>Pawel Lampe: WPE memory leak investigation playbook</title>
	<guid>https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/</guid>
	<link>https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/</link>
	<description>
&lt;!-- ############################################ SWEEP  ############################################--&gt;
&lt;p&gt;Depending on the web application, the WPE WebKit memory usage trend can vary. When simple web applications are being processed, the memory consumption tends to be virtually stable (the same) no matter the period. However, when more complicated web applications
are being executed, the memory usage usually grows over time while going back to normal from time to time e.g., when GC / memory pressure mechanism releases all kinds of caches and not-needed memory. Therefore, memory growth itself is not unusual.
Nevertheless, as the memory leaks happen in WPE at times, the memory growth is worth investigating &#8212; especially if very rapid or unbounded.&lt;/p&gt;
&lt;p&gt;This article presents a structured playbook for investigating such a memory growth and memory leaks in WPE. Rather than diving straight into debugging tools, it starts from first principles: confirming the problem is real, choosing the right
environment to work in, and narrowing down the leaking area before any heavy tooling is involved. The goal is to reach actual debugging as fast as possible, regardless of whether the environment is an embedded device or a desktop machine,
and regardless of how quickly the problem reproduces.&lt;/p&gt;
&lt;h2 id=&quot;playbook&quot; tabindex=&quot;-1&quot;&gt;Playbook &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The high-level list of recommended steps to follow is presented below. In a nutshell, the steps &lt;strong&gt;1&lt;/strong&gt;, &lt;strong&gt;2&lt;/strong&gt;, and &lt;strong&gt;3&lt;/strong&gt; are meant to choose and follow the fastest possible investigation path so that actual debugging of the problem
(step &lt;strong&gt;4&lt;/strong&gt;) can be started as soon as possible.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Confirming the problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Identifying the best setup for reproducing the problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Narrowing down&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;on &lt;strong&gt;embedded&lt;/strong&gt; when the problem takes a &lt;strong&gt;long time&lt;/strong&gt; to reproduce&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;on &lt;strong&gt;embedded&lt;/strong&gt; when the problem reproduces &lt;strong&gt;quickly&lt;/strong&gt;&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;on &lt;strong&gt;desktop&lt;/strong&gt; when the problem takes a &lt;strong&gt;long time&lt;/strong&gt; to reproduce&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;on &lt;strong&gt;desktop&lt;/strong&gt; when the problem reproduces &lt;strong&gt;quickly&lt;/strong&gt;&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Debugging&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;1-confirming-the-problem&quot; tabindex=&quot;-1&quot;&gt;1. Confirming the problem &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The ultimate first step when working with alleged memory leak is to check whether the observed memory growth is actually abnormal. In the case of web browsers in general, the memory growth alone may not necessarily mean something is leaking.
&lt;strong&gt;There may be many regular reasons why the browser&#8217;s memory usage is growing&lt;/strong&gt;, but the usual suspects are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JavaScript-level memory allocations&lt;/strong&gt; &#8212; due to the very nature of JavaScript, the memory it allocates causes the overall web content process memory growth up until the garbage collector (GC) kicks in. Then (from the RSS perspective) some memory
is usually freed. However, as it&#8217;s not easy to predict when the GC will be invoked (e.g., when the browser processes an application that performs heavy rendering), it&#8217;s possible that memory will grow but remain garbage-collectible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript Just-in-Time (JIT) compilation&lt;/strong&gt; &#8212; when not explicitly disabled or limited, the processing of any web application that has JavaScript code associated with it will cause the browser to continuously compile the JavaScript code in the
background so that it executes such code faster in runtime at the expense of memory that is required for storing compiled artifacts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caches&lt;/strong&gt; &#8212; as the WPE operates, it caches things such as web resources, style resolution artifacts, textures, glyph atlases, layer tiles, display lists, rasterization artifacts, and many others. Naturally, the cache sizes are limited, however,
if many caches are growing at the same time, they may create an impression of a leak. The difference in that case is, the caches stop growing at some point.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Due to the above, to confirm the memory growth is abnormal, one should usually try the following first:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Triggering memory pressure&lt;/a&gt; to force the browser to trigger GC and evict as many cache entries as possible,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Rerunning the browser with JIT disabled&lt;/a&gt; to rule out the JIT-related memory growth &#8212; unless the application code is very small.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the memory growth doesn&#8217;t stop with JIT disabled or its level does not go back to normal after triggering memory pressure, the growth can be assumed to be abnormal, and one can proceed to the next step.&lt;/p&gt;
&lt;h3 id=&quot;2-identifying-the-best-setup-for-reproducing-the-problem&quot; tabindex=&quot;-1&quot;&gt;2. Identifying the best setup for reproducing the problem &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the memory growth is atypical, it needs to be narrowed down in a way that the final debugging is possible. For both narrowing down and the debugging, &lt;strong&gt;one should aim at the most flexible development environment along with the smallest possible
web application that reproduces the problem quickly&lt;/strong&gt;. What it means in practice is &#8212; desktop environment along with small demo web application that reproduces the problem. Whilst it&#8217;s not always possible to have such an environment, the 3 general
rules are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Desktop environment is usually better than embedded one&lt;/strong&gt; in terms of working with memory leaks as it offers minimal overhead (e.g., in terms of compilation times) and huge flexibility in choosing the industry standard tools for profiling/debugging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Small web application is always better than a big one as long as it still reproduces the same problem in the same amount of time&lt;/strong&gt;. In such case, a small application minimizes the amount of noise that usually stands in the way of profiling/debugging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A web application that reproduces the problem quickly is always better than the one that needs much more time for it&lt;/strong&gt;. The worst thing that can happen in the case of narrowing down memory leaks, is when the memory growth is noticeable or starts
after a very long time such as hours/days+.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given the above, at this point one should go through the below steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Check if the setup is trivial enough already&lt;/strong&gt; &#8212; if the web application reproduces the problem quickly in a desktop environment and is simple enough, one should immediately jump to the &lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Debugging&lt;/a&gt; section.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check if the problem can be reproduced on desktop assuming it originally reproduces on embedded&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check if the problem can be reproduced faster if it&#8217;s not reproducing fast enough&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check if the web application could be simplified.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once the setup is simplified as much as possible, one should proceed to one of &lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;narrowing down&lt;/a&gt; sections depending on the setup. Also, if the setup is still not ideal, one should actively seek opportunities for simplifying the setup
even during &lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;narrowing down&lt;/a&gt; as it&#8217;s likely that some new information will eventually open new possibilities in terms of simplifying setup.&lt;/p&gt;
&lt;h3 id=&quot;3-narrowing-down&quot; tabindex=&quot;-1&quot;&gt;3. Narrowing down &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the problem has been confirmed but there are not enough clues to tell exactly which parts leak, the &lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;debugging&lt;/a&gt; cannot be started right away. In such case, it&#8217;s necessary to narrow down the problem to the browser/application area
that can be easily debugged.&lt;/p&gt;
&lt;p&gt;While in some cases narrowing down is not even necessary, quite often it takes orders of magnitude more time than actual debugging, and hence one should pay special attention to this step.&lt;/p&gt;
&lt;h3 id=&quot;3a-narrowing-down-on-embedded-when-the-problem-takes-a-long-time-to-reproduce&quot; tabindex=&quot;-1&quot;&gt;3a. Narrowing down on embedded when the problem takes a long time to reproduce &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the toughest situation one can find themselves in. When a problem takes a long time to reproduce (hours/days+), every iteration/test comes automatically with a significant cost. Moreover, when the environment is an embedded one,
rebuilding WPE is usually more time-consuming and the amount of tooling is usually limited &#8212; or requires some work to bring it to the image at least.&lt;/p&gt;
&lt;p&gt;Due to the above, narrowing down the problem in this setup requires a structured approach with extra care. In such case, the things to check should be approached in steps defined as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rerunning the WebKit&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;in case of embedded devices, extra care is needed when attaching a memory profiler. On low-end devices, memory profilers tend to slow down the application hard enough to trigger otherwise non-existent problems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rebuilding the WebKit&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;in case of embedded devices, one should prefer limiting JIT over disabling it as without it, the JS execution may be slow enough to trigger unexpected scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check if rebuilding WebKit&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ideally, while checking various things along the above steps, one should batch as many checks as possible within individual tests.&lt;/p&gt;
&lt;h3 id=&quot;3b-narrowing-down-on-embedded-when-the-problem-reproduces-quickly&quot; tabindex=&quot;-1&quot;&gt;3b. Narrowing down on embedded when the problem reproduces quickly &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the problem reproduces quickly, the limitations of embedded environment are not that relevant. In this scenario, one should prioritize getting debug symbols (&lt;code&gt;RelWithDebInfo&lt;/code&gt; build) into the image and utilizing them by running
the browser with whatever profilers are available. For the specific things to check, one should seek inspiration in the following groups:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rebuilding the WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check if rebuilding WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;3c-narrowing-down-on-desktop-when-the-problem-takes-a-long-time-to-reproduce&quot; tabindex=&quot;-1&quot;&gt;3c. Narrowing down on desktop when the problem takes a long time to reproduce &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This situation is similar to &lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;3a&lt;/a&gt; and hence one should follow the things to check from the following groups:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rerunning the WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rebuilding the WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check if rebuilding WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, this time, there are some extra opportunities around tooling:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There should be many more tools available already in the system or available to be installed.&lt;/li&gt;
&lt;li&gt;Tools such as memory profilers that could slow down the application making it unusable on embedded, may turn out to be working well when the desktop-class processing power is available.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the above in mind, it&#8217;s worth trying all the tools available with priority because if at least one tool works well, one can save hours of narrowing down.&lt;/p&gt;
&lt;h3 id=&quot;3d-narrowing-down-on-desktop-when-the-problem-reproduces-quickly&quot; tabindex=&quot;-1&quot;&gt;3d. Narrowing down on desktop when the problem reproduces quickly &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is technically the simplest possible scenario, so basically, all the possibilities are available. The most time-consuming activity in this case is very likely rebuilding WebKit itself &#8212; although it should still be relatively fast.
In such case, just after a few quick checks with the Web Inspector, it&#8217;s recommended to get debug symbols (&lt;code&gt;RelWithDebInfo&lt;/code&gt; build) and start with tools such as memory profilers.&lt;/p&gt;
&lt;p&gt;Other than the above, one should go through the following groups on things to check:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check without rebuilding the WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Things to check if rebuilding WebKit&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;4-debugging&quot; tabindex=&quot;-1&quot;&gt;4. Debugging &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The WPE debugging is twofold and depends on whether the problem is within the engine (usually C/C++ code) or the web application (JavaScript code).&lt;/p&gt;
&lt;h4 id=&quot;when-problem-lies-in-the-engine&quot; tabindex=&quot;-1&quot;&gt;When problem lies in the engine &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Debugging WPE WebKit is the same as debugging any other C/C++ application on Linux (or Mac if the issue is cross-port and one prefers an Apple port to work with), and hence is outside the scope of this article. Some WebKit-specific information
can be found in the &lt;a href=&quot;https://docs.webkit.org/Build%20%26%20Debug/BuildOptions.html&quot;&gt;WebKit Documentation article on building and debugging&lt;/a&gt; page and therefore is recommended as a first step.&lt;/p&gt;
&lt;h4 id=&quot;when-problem-lies-in-web-application&quot; tabindex=&quot;-1&quot;&gt;When problem lies in web application &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When the problem lies in JavaScript code, the situation is usually fairly straightforward. The majority of bugs in this area should be reproducible across various browser engines and hence a full variety of tooling should be available.
If the WebKit is preferred or if the problem reproduces only there, the tooling available is still very useful and helps debugging problems quickly. The ultimate tool in such case is the
&lt;a href=&quot;https://developer.apple.com/documentation/safari-developer-tools/web-inspector&quot;&gt;Web Inspector&lt;/a&gt;. On official WebKit&#8217;s web page there&#8217;s entire index of &lt;a href=&quot;https://webkit.org/web-inspector/&quot;&gt;articles on Web Inspector&lt;/a&gt;. Among those, the most interesting
read is about &lt;a href=&quot;https://webkit.org/web-inspector/timelines-tab/&quot;&gt;Timelines Tab&lt;/a&gt; where the most useful debugging can be done. Once the features of &lt;strong&gt;Timelines Tab&lt;/strong&gt; are understood, the next important article is
&lt;a href=&quot;https://webkit.org/blog/6425/memory-debugging-with-web-inspector/&quot;&gt;the memory debugging guide&lt;/a&gt;. It dives into the most important &lt;strong&gt;Timelines Tab&lt;/strong&gt; subsections and showcases the work with heap snapshots which is a key. To supplement it,
it&#8217;s very important to know the &lt;strong&gt;heap snapshot delta&lt;/strong&gt; feature which is basically about button:&lt;/p&gt;
&lt;center&gt;
&lt;source type=&quot;image/avif&quot;&gt;&lt;source type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Web Inspector heap delta.&quot; src=&quot;https://blogs.igalia.com/plampe/img/eSkdO_v8QP-1261.png&quot; width=&quot;1261&quot; height=&quot;285&quot; /&gt;
&lt;/source&gt;&lt;/source&gt;&lt;/center&gt;
&lt;p&gt;that allows one to inspect the delta-snapshot between 2 snapshots. It&#8217;s critical as it answers the question on what JS objects were added between the base snapshot and the later one. If some objects are piling up, it immediately shows
which ones.&lt;/p&gt;
&lt;p&gt;One important note on snapshots is that in some cases when using Web Inspector is not possible, one can generate the snapshots manually from the web engine&#8217;s C++ code by just calling &lt;code&gt;GarbageCollectionController::singleton().dumpHeap();&lt;/code&gt; at
some appropriate moment. In this case, the dump will be written to standard output. It can be then turned into a file and imported from any &lt;strong&gt;Web Inspector&lt;/strong&gt; using &lt;strong&gt;Import&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;As the &lt;strong&gt;Timelines Tab&lt;/strong&gt; with its subsections should be able to answer on &lt;em&gt;what happens&lt;/em&gt;, to understand &lt;em&gt;why&lt;/em&gt; it actually happens, the last missing piece is the JS debugger within &lt;strong&gt;Web Inspector&lt;/strong&gt;. It&#8217;s not very different to debuggers in
other engines, but it&#8217;s worth checking a &lt;a href=&quot;https://webkit.org/web-inspector/javascript-breakpoints/&quot;&gt;dedicated article&lt;/a&gt; on it just to understand the capabilities.&lt;/p&gt;
&lt;h2 id=&quot;appendix&quot; tabindex=&quot;-1&quot;&gt;Appendix &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;things-to-check-without-rerunning-the-webkit&quot; tabindex=&quot;-1&quot;&gt;Things to check without rerunning the webkit &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Even if the WPE is running with default settings in release mode, there are plenty of useful things that can be checked while the browser is still running:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Identifying which WebKit process allocates abnormally,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;there are multiple ways to do this, but usually it&#8217;s as easy as using &lt;code&gt;ps&lt;/code&gt; utility.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identifying how fast the process in question allocates the memory,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;this is useful to know at least for comparison purposes, but it may hint some problems already if the numbers correlate with what web application does.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checking logs from stdout, stderr, and journal (using &lt;code&gt;journalctl&lt;/code&gt;).&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Checking detailed process memory statistics&lt;/a&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Triggering and checking the impact of memory pressure&lt;/a&gt; on given processes RSS,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;in short, memory pressure triggers the cleanup of the majority of caches along with GC. Therefore, if this is able to bring memory back to normal level, then the problem is about caches, JS Heap / GC, or fragmentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Attaching memory profilers&lt;/a&gt; if available,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;even if the debug symbols are not present, this may be useful to see what data is being captured and how the web application behaves when slowed down by profiler.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Attaching other tools&lt;/a&gt; if available,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;even if the debug symbols are not present, various tools offer different perspectives on what the browser is doing. In some cases, such information may reveal some anomalies that may be related to the main issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-checking with other browsers,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if other browsers show a similar pattern of memory usage, it&#8217;s very likely the problem lies in web application itself. Otherwise, it strongly suggests a bug in the WPE.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-checking with other ports,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if any other WebKit port shows a similar pattern of memory usage, it allows one to narrow down the area in the code a bit based on what port it is:
&lt;ul&gt;
&lt;li&gt;if the same behavior is visible in any of &lt;strong&gt;Apple&lt;/strong&gt; ports, the problem is most likely related to cross-platform code,&lt;/li&gt;
&lt;li&gt;if the same behavior is visible only in &lt;strong&gt;GTK&lt;/strong&gt; port, then the problem is most likely related to GLib-related part, coordinated graphics part, GStreamer-related part, or others that are shared.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;things-to-check-without-rebuilding-the-webkit&quot; tabindex=&quot;-1&quot;&gt;Things to check without rebuilding the webkit &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Tweaking and checking the logs from WPE&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;while generic logs may hint some unusual behavior, more specific ones such as GC logs (&lt;code&gt;JSC_logGC=1&lt;/code&gt;) may be used to check how the individual JS heap sizes evolve over time and how GC behaves. &lt;strong&gt;If it&#8217;s JavaScript
leaking the memory, this log will quickly provide the evidence&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Enabling Remote Web Inspector&lt;/a&gt; and checking:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;both breakdown and trend of memory usage in the &lt;a href=&quot;https://webkit.org/web-inspector/timelines-tab/#memory-timeline&quot;&gt;memory timeline&lt;/a&gt; after doing a bit of recording,&lt;/li&gt;
&lt;li&gt;the effects of &lt;code&gt;takeHeapSnapshot()&lt;/code&gt; invoked from JS console:
&lt;ul&gt;
&lt;li&gt;as this function usually triggers GC internally, it may be used to check how much RSS memory is reclaimed by GC in isolation (followed up by scavenger),&lt;/li&gt;
&lt;li&gt;as this function takes a JS heap snapshot, it then can be used to explore &lt;a href=&quot;https://webkit.org/blog/6425/memory-debugging-with-web-inspector/&quot;&gt;manually&lt;/a&gt; if its contents point towards something interesting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Disabling JIT&lt;/a&gt; and checking the memory usage,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if the memory usage is stable with JIT disabled, one should proceed to the step below.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Limiting JIT&lt;/a&gt; and checking the memory usage,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;there are at least a few places (levels) where JIT compilation engine allocates memory. If limiting doesn&#8217;t resolve the issue completely, it&#8217;s likely the engine itself leaks some memory around temporary helper-heaps such as &lt;code&gt;AssemblerData&lt;/code&gt; etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Experimenting with environment variables and runtime preferences&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;some environment variables and runtime preferences change the behavior of the web engine significantly. If changing one of them makes the problem go away, it usually helps to narrow down the problematic area quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Running WPE with system malloc (environment variable &lt;code&gt;Malloc=1&lt;/code&gt;) and checking the memory usage,&lt;/strong&gt; &lt;!-- comparing memory usage vs bmalloc/libpas,** &lt;\!-- (`Malloc=1`) -\-&gt; --&gt;
&lt;ul&gt;
&lt;li&gt;when one suspects bmalloc/libpas issues with fragmentation or scavenger, it&#8217;s worth running a browser with system malloc to compare the memory evolution over time against the bmalloc/libpas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Limiting device memory&lt;/a&gt; and checking the memory usage,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if &lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;triggering memory pressure&lt;/a&gt;&lt;/strong&gt; is not possible, an alternative solution is to limit the device memory so that the browser is under constant memory pressure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Running WPE with sysprof&lt;/a&gt; and checking:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;stack traces&lt;/strong&gt; &#8212; to see what parts of engine are particularly active as it may hint some problematic area,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebKit marks&lt;/strong&gt; &#8212; to see what the engine is doing as well as quantitative data in marks such as &lt;code&gt;EventLoopRun&lt;/code&gt; etc. as in those cases the numeric value trends may reveal resource pile up.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;things-to-check-if-rebuilding-webkit&quot; tabindex=&quot;-1&quot;&gt;Things to check if rebuilding webkit &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Building WPE in release mode with debug symbols&lt;/a&gt; and re-trying memory profilers or other tools if the debug symbols were not present before,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if some desired tools such as &lt;strong&gt;heaptrack&lt;/strong&gt;, &lt;strong&gt;valgrind&lt;/strong&gt;, &lt;strong&gt;perf&lt;/strong&gt;, or &lt;strong&gt;strace&lt;/strong&gt; were not available before, it&#8217;s the right moment to get/build them as well,&lt;/li&gt;
&lt;li&gt;once the debug symbols are in, one should try:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;attaching memory profilers&lt;/a&gt;&lt;/strong&gt; if available, and inspecting detailed memory allocation reports,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;attaching other tools&lt;/a&gt;&lt;/strong&gt; if available, and investigating the traces.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building and running with Google perftools,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;as WPE allows switching to system malloc as an allocator, it&#8217;s possible to use custom malloc implementation with instrumentation such as &lt;a href=&quot;https://github.com/gperftools/gperftools&quot;&gt;gperftools&lt;/a&gt;. For that, the recommended read is
&lt;a href=&quot;https://http503.gvatas.in/2024/10/09/diagnosing-memory-leaks-in-wpewebkit-with-google-perftools/&quot;&gt;this article&lt;/a&gt; from fellow Igalian, Pablo Saavedra.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Building and running with sanitizers&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;if the problem is about low-level leak, address/leak sanitizer should be able to help pointing out the problematic area.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Building and running with memory sampler&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;the data produced by memory sampler is roughly the same as inspector&#8217;s &lt;a href=&quot;https://webkit.org/web-inspector/timelines-tab/#memory-timeline&quot;&gt;memory timeline&lt;/a&gt;, however, it&#8217;s much more convenient as it doesn&#8217;t need web inspector at all.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Building and running with node statistics&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;when memory growth seems to be related to DOM mutations, it&#8217;s worth enabling and reporting node statistics periodically &#8212; in some cases, it may directly suggest what the problem is about.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building and running with malloc heap breakdown,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;when all other means fail, a very good last-resort approach for investigating memory usage statistics via a debug-only WebKit feature called &lt;strong&gt;Malloc Heap Breakdown&lt;/strong&gt;. The details can be found in
&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/tracking-webkit-s-memory-allocations-with-malloc-heap-breakdown/&quot;&gt;the dedicated article about it&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;Building and running with libpas statistics&lt;/a&gt;,&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;On very rare occasions such as memory fragmentation or allocation issues, it may be worth checking the &lt;a href=&quot;https://docs.webkit.org/Deep%20Dive/Libpas/Libpas.html&quot;&gt;libpas&lt;/a&gt; (low-level memory allocation and management library)
statistics as WPE uses it by default on the vast majority of platforms.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;individual-instructions&quot; tabindex=&quot;-1&quot;&gt;Individual instructions &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;checking-detailed-process-memory-statistics&quot; tabindex=&quot;-1&quot;&gt;Checking detailed process memory statistics &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;As WPE WebKit uses multi-process architecture, there are multiple processes that can be checked, although the most interesting one is usually the &lt;strong&gt;Web Content Process&lt;/strong&gt;. Once the PID of the given process is determined (e.g., using &lt;code&gt;ps&lt;/code&gt; utility)
the usual steps to check detailed memory statistics are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cat /proc/&amp;lt;PID&amp;gt;/status&lt;/code&gt; or &lt;code&gt;cat /proc/&amp;lt;PID&amp;gt;/statm&lt;/code&gt; for very basic statistics,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pmap -X &amp;lt;PID&amp;gt;&lt;/code&gt; - for detailed statistics (if available),&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cat /proc/&amp;lt;PID&amp;gt;/smaps_rollup&lt;/code&gt; and &lt;code&gt;cat /proc/&amp;lt;PID&amp;gt;/smaps&lt;/code&gt; for detailed statistics (requires &lt;code&gt;CONFIG_PROC_PAGE_MONITOR&lt;/code&gt; kernel configuration option).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;triggering-memory-pressure-from-os&quot; tabindex=&quot;-1&quot;&gt;Triggering memory pressure from OS &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;WPE uses a so-called &lt;strong&gt;Memory Pressure Monitor&lt;/strong&gt; to observe the memory usage in the system and to react if there&#8217;s not much memory left. The default thresholds are specified in &lt;code&gt;MemoryPressureMonitor.cpp&lt;/code&gt; and usually are
90% for non-critical and 95% for critical response. Depending on the response, WPE schedules GC and clears internal caches immediately.&lt;/p&gt;
&lt;p&gt;As the above is usually on by default, one can leverage it to trigger GC (along with cache cleanups) by filling up the available memory in the OS to 95+%. There are many ways to allocate memory, yet the simplest is using &lt;code&gt;stress&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;stress --vm 1 --vm-bytes 1024M --vm-keep&lt;/code&gt; to allocate 1024 MB.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;attaching-memory-profilers&quot; tabindex=&quot;-1&quot;&gt;Attaching memory profilers &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When attaching any memory profiler, unless one wants to profile only native allocations (Skia, GStreamer, ICU, etc.), the key is to use &lt;code&gt;Malloc=1&lt;/code&gt; environment variable on WPE startup so that bmalloc uses system malloc instead of libpas.
Also, if WebKit is using a sanboxed mode in given configuration, it&#8217;s usually necessary to use &lt;code&gt;WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1&lt;/code&gt; as well. Then the commands are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to attach &lt;strong&gt;heaptrack&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;heaptrack -p &amp;lt;PID&amp;gt;&lt;/code&gt; so e.g. &lt;code&gt;heaptrack -p $(pgrep WPEWebProcess)&lt;/code&gt; (see &lt;a href=&quot;https://blogs.igalia.com/plampe/tracking-webkit-s-memory-allocations-with-malloc-heap-breakdown/#heaptrack&quot;&gt;this article&lt;/a&gt; for details),&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;to run with &lt;strong&gt;valgrind&#8217;s massif&lt;/strong&gt; (as attaching to running process is not possible):
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;valgrind --tool=massif --trace-children=yes &amp;lt;WPE-BROWSER-COMMAND&amp;gt;&lt;/code&gt; (see &lt;a href=&quot;https://blogs.igalia.com/plampe/tracking-webkit-s-memory-allocations-with-malloc-heap-breakdown/#massif-valgrind&quot;&gt;this article&lt;/a&gt; for details).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;attaching-other-tools&quot; tabindex=&quot;-1&quot;&gt;Attaching other tools &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If memory profilers are unusable or unavailable, it&#8217;s worth checking if other tools are present and experimenting a bit with them if so. In some cases, tools other than memory profilers may give some hints on further investigation
or reveal a suspicious pattern within application execution. Some ideas for experiments with various tools are listed below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;strace:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strace -c -p $(pgrep WPEWebProcess)&lt;/code&gt; &#8212; &lt;strong&gt;strace&lt;/strong&gt; called with &lt;code&gt;-c&lt;/code&gt; gives a nice summary of system calls executed by the traced application. It can be useful to check the overall syscall usage pattern to see if there are any anomalies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strace -p $(pgrep WPEWebProcess) -e trace=mmap,munmap,mremap,madvise -tt&lt;/code&gt; &#8212; &lt;strong&gt;strace&lt;/strong&gt; focused on &lt;code&gt;mmap()&lt;/code&gt;-related system calls may be useful to debug libpas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;perf:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;perf record -F 999 -ag -p $(pgrep WPEWebProcess) -- sleep 60&lt;/code&gt; &#8212; regular recording with &lt;strong&gt;perf&lt;/strong&gt; can be very useful, especially if symbols are available. With that, one can generate
&lt;a href=&quot;https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html&quot;&gt;flamegraphs&lt;/a&gt; and investigate what&#8217;s going on in the browser. While it&#8217;s not about profiling memory, it may be helpful to narrow down at least a bit.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;perf record -F 999 -e syscalls:sys_enter_mmap,syscalls:sys_enter_munmap,syscalls:sys_enter_mremap:sys_enter_madvise -ag -p $(pgrep WPEWebProcess) -- sleep 60&lt;/code&gt; &#8212; &lt;strong&gt;perf&lt;/strong&gt; focused on &lt;code&gt;mmap()&lt;/code&gt;-related system calls is much more superior
than e.g. &lt;strong&gt;strace&lt;/strong&gt; as it also records stack traces. Therefore, if debug symbols are present, and if the memory growth is very rapid, it&#8217;s very likely the libpas &lt;code&gt;mmap()&lt;/code&gt; stacktraces will lead to the growth origin statistically.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;perf trace -e mmap,munmap,mremap,madvise -p $(pgrep WPEWebProcess)&lt;/code&gt; &#8212; this is very much similar to &lt;strong&gt;strace&lt;/strong&gt; focused on &lt;code&gt;mmap()&lt;/code&gt;-related system calls as it shows a live preview of what&#8217;s happening.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sysprof:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sysprof-cli -f&lt;/code&gt; &#8212; while running system-wide &lt;strong&gt;sysprof&lt;/strong&gt; won&#8217;t make WPE push marks into it, the profiling trace may still be useful to some degree, especially if debug symbols are available.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;disabling-jit&quot; tabindex=&quot;-1&quot;&gt;Disabling JIT &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This can be done using an environment variable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JSC_useJIT=false&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;limiting-jit&quot; tabindex=&quot;-1&quot;&gt;Limiting JIT &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Limiting JIT can be achieved via environment variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JSC_jitMemoryReservationSize=&amp;lt;BYTES&amp;gt;&lt;/code&gt; to limit JIT memory usage (the limit is semi-strict as some JIT compilation engine buffers are limited by this value indirectly),&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC_useFTLJIT=false&lt;/code&gt; to disable FTL tier,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC_useDFGJIT=false&lt;/code&gt; to disable DFG and FTL tiers,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC_useBaselineJIT=false&lt;/code&gt; to disable Baseline, DFG, and FTL tiers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;tweaking-wpe-logs&quot; tabindex=&quot;-1&quot;&gt;Tweaking WPE logs &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;WPE is a fairly complex piece of software and hence it offers various logging capabilities related to WebKit itself, as well as to related libraries. The vast majority of logging can be controlled via environment variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_DEBUG=all&lt;/code&gt; to enable all logging channels,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_DEBUG=Layout,Media=debug,Events=debug&lt;/code&gt; to enable selected logging channels,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSC_logGC=2&lt;/code&gt; to enable JS garbage collector logs,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GST_DEBUG=4&lt;/code&gt; to enable gstreamer (multimedia-related) logs (see &lt;a href=&quot;https://gstreamer.freedesktop.org/documentation/tutorials/basic/debugging-tools.html?gi-language=c#printing-debug-information&quot;&gt;the documentation&lt;/a&gt;),&lt;/li&gt;
&lt;li&gt;&lt;code&gt;G_MESSAGES_DEBUG=all&lt;/code&gt; to enable GLib-level logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;strong&gt;MiniBrowser&lt;/strong&gt; (or similar browser) is used, one can also set a runtime preference to enable JS &lt;code&gt;console.log(...)&lt;/code&gt; logging to the standard output:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--features=+LogsPageMessagesToSystemConsole&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;enabling-remote-web-inspector&quot; tabindex=&quot;-1&quot;&gt;Enabling remote web inspector &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Enabling WPE&#8217;s remote web inspector is a twofold process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The first step is to run WPE with the proper environment variable so that it starts listening on &lt;code&gt;IP:PORT&lt;/code&gt; using tcp socket:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_INSPECTOR_SERVER=IP:PORT&lt;/code&gt; is the most reasonable option as it uses &lt;code&gt;inspector://&lt;/code&gt; protocol that can be utilized by WebKit-native browsers such as &lt;a href=&quot;https://apps.gnome.org/Epiphany/&quot;&gt;GNOME Web (Epiphany)&lt;/a&gt; or Safari,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_INSPECTOR_HTTP_SERVER=IP:PORT&lt;/code&gt; is a less preferable alternative that uses HTTP protocol and technically works from any browser. However, no seamless integration is guaranteed in this case.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;The second step is to connect from a regular web browser to the WPE:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;using &lt;code&gt;inspector://IP:PORT/&lt;/code&gt; if native inspector server was started,&lt;/li&gt;
&lt;li&gt;using &lt;code&gt;http://IP:PORT/&lt;/code&gt; if HTTP inspector server was started,&lt;/li&gt;
&lt;li&gt;forwarding the ports using &lt;code&gt;socat tcp-l:PORT,fork,reuseaddr tcp:IP:PORT&lt;/code&gt; if the WPE is running in unreachable network.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;experimenting-with-environment-variables-and-runtime-preferences&quot; tabindex=&quot;-1&quot;&gt;Experimenting with environment variables and runtime preferences &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The most outstanding environment variables changing the behavior of WPE are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WPE_DISPLAY&lt;/code&gt; &#8212; assuming the &lt;a href=&quot;https://wpewebkit.org/blog/2026-03-18-wpewebkit-2.52.html#api-changes&quot;&gt;new WPE platform API&lt;/a&gt; is used, this environment variable allows one to switch the pre-defined platform implementation thus
changing a platform-facing part of graphics pipeline. The valid options are:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WPE_DISPLAY=wpe-display-headless&lt;/code&gt; &#8212; for headless implementation,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WPE_DISPLAY=wpe-display-drm&lt;/code&gt; &#8212; for direct rendering manager integration,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WPE_DISPLAY=wpe-display-wayland&lt;/code&gt; &#8212; for wayland integration,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_SKIA_ENABLE_CPU_RENDERING&lt;/code&gt; &#8212; when set to &lt;code&gt;1&lt;/code&gt;, rendering the DOM contents to the layers is done using Skia CPU backend instead of GPU one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most outstanding runtime preferences changing the behavior of WPE are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CanvasUsesAcceleratedDrawing&lt;/code&gt; &#8212; when disabled, 2D canvas will use Skia CPU backend instead of GPU one,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LayerBasedSVGEngine&lt;/code&gt; &#8212; when enabled, WPE uses a different SVG engine internally,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AcceleratedCompositing&lt;/code&gt; &#8212; when disabled, WPE uses experimental, non-composited mode that bypasses all of the compositor work.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;limiting-device-memory&quot; tabindex=&quot;-1&quot;&gt;Limiting device memory &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;On the majority of embedded devices, the device memory can be limited by:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Interrupting the boot sequence (usually holding some key such as &lt;code&gt;z&lt;/code&gt; upon booting),&lt;/li&gt;
&lt;li&gt;Invoking the command to change the limit and booting, e.g.:&lt;pre&gt;&lt;code&gt;&amp;gt; global linux.bootargs.console=&amp;quot;console=ttymxc0,115200n8 mem=2G&amp;quot;
&amp;gt; boot
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;running-wpe-with-sysprof&quot; tabindex=&quot;-1&quot;&gt;Running WPE with sysprof &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Regardless of whether it&#8217;s done on desktop (using &lt;a href=&quot;https://github.com/Igalia/webkit-container-sdk&quot;&gt;wkdev-sdk&lt;/a&gt;) or on embedded device, the command is always as simple as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sysprof-cli -f -- &amp;lt;WPE-INVOCATION&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a href=&quot;https://wpewebkit.org/reference/unstable/wpe-webkit-2.0/profiling.html#profiling-with-sysprof&quot;&gt;the documentation entry&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h4 id=&quot;building-wpe-in-release-mode-with-debug-symbols&quot; tabindex=&quot;-1&quot;&gt;Building WPE in release mode with debug symbols &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;On desktop, the simplest way to get release with debug symbols is to utilize CMake&#8217;s build type by using &lt;code&gt;-DCMAKE_BUILD_TYPE=RelWithDebInfo&lt;/code&gt; within WPE build command, so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;./Tools/Scripts/build-webkit --wpe --release --cmakeargs=&amp;quot;-DCMAKE_BUILD_TYPE=RelWithDebInfo&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On embedded, when Yocto is used, one should tweak settings such as:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;IMAGE_GEN_DEBUGFS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;                                                         &lt;br /&gt;IMAGE_FSTYPES_DEBUGFS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tar.bz2&quot;&lt;/span&gt;&lt;br /&gt;DEBUG_BUILD &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;br /&gt;EXTRA_IMAGE_FEATURES_append &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; dbg-pkgs&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and potentially &lt;code&gt;INHIBIT_PACKAGE_STRIP&lt;/code&gt; to control whether debug symbols should be kept with the binary or not. This may be necessary occasionally as some tools have problems reading &lt;code&gt;.gnu_debuglink&lt;/code&gt; and therefore work only
with symbols included in the binaries.&lt;/p&gt;
&lt;h4 id=&quot;building-and-running-with-sanitizers&quot; tabindex=&quot;-1&quot;&gt;Building and running with sanitizers &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;WebKit works pretty well with all kinds of sanitizers. To build with any of them a CMake-level helper called &lt;code&gt;ENABLE_SANITIZERS&lt;/code&gt; can be used by specifying &lt;code&gt;-DENABLE_SANITIZERS=address&lt;/code&gt;, &lt;code&gt;-DENABLE_SANITIZERS=leak&lt;/code&gt; etc. With that, the command for
building e.g. on desktop could look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;./Tools/Scripts/build-webkit --wpe --debug --cmakeargs=-DENABLE_SANITIZERS=address&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more details, one can refer to &lt;a href=&quot;https://blogs.igalia.com/fujii/building-webkit-and-libsoup-with-addresssanitizer-asan/&quot;&gt;this article&lt;/a&gt; from fellow Igalian, Fujii.&lt;/p&gt;
&lt;h4 id=&quot;building-and-running-with-memory-sampler&quot; tabindex=&quot;-1&quot;&gt;Building and running with memory sampler &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When WPE is built with &lt;code&gt;-DENABLE_MEMORY_SAMPLER=ON&lt;/code&gt;, the simple memory sampler can be started along with the browser using environment variable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WEBKIT_SAMPLE_MEMORY=1&lt;/code&gt; (accompanied by &lt;code&gt;WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1&lt;/code&gt; if needed).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that, the memory of various WPE processes is sampled every second, and saved to the files under &lt;code&gt;/tmp&lt;/code&gt; directory continuously.&lt;/p&gt;
&lt;h4 id=&quot;building-and-running-with-node-statistics&quot; tabindex=&quot;-1&quot;&gt;Building and running with node statistics &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Node statistics are a debug-only feature that can be enabled by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;changing &lt;code&gt;0&lt;/code&gt; of &lt;code&gt;#define DUMP_NODE_STATISTICS 0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; in &lt;code&gt;Source/WebCore/dom/Element.h&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;adding &lt;code&gt;dumpStatistics()&lt;/code&gt; call, to e.g. &lt;code&gt;Node&lt;/code&gt; constructor in &lt;code&gt;Source/WebCore/dom/Node.cpp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;building-and-running-with-libpas-statistics&quot; tabindex=&quot;-1&quot;&gt;Building and running with libpas statistics &lt;a class=&quot;header-anchor&quot; href=&quot;https://blogs.igalia.com/plampe/wpe-memory-leak-investigation-playbook/&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Libpas statistics are a debug-only feature that can be enabled by changing &lt;code&gt;0&lt;/code&gt; of &lt;code&gt;#define PAS_ENABLE_STATS 0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; in &lt;code&gt;Source/bmalloc/libpas/src/libpas/pas_config.h&lt;/code&gt; and then running WPE with environment variable &lt;code&gt;PAS_STATS_ENABLE=1&lt;/code&gt;.&lt;/p&gt;        </description>
	<pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate>
</item>

</channel>
</rss>
