Servo now supports several new web API features:
- :host selector (@simonwuelker, #34870)
- <slot> elements in the DOM (@simonwuelker, #35013, #35177, #35191, #35221, #35137, #35222), with layout support landing next month
- Relative CSS colors, like color(from …) and rgb(from …) (@Loirooriol, #34897)
- ClipboardEvent (@Gae24, #33576, #35146), with
--pref dom_clipboardevent_enabled
- Detecting WGSL extensions via WGSLLanguageFeatures (@sagudev, #34928)
- pointer_composite_access WGSL extension (@sagudev, #35161)
- blitFramebuffer() on WebGL2RenderingContext (@jdm, Istvan, #26389)
- media property on HTMLStyleElement (@webbeef, #35148)
We’ve landed a bunch of HTMLCanvasElement improvements:
- toDataURL() now supports image/jpeg and image/webp (@webbeef, #34861)
- toBlob() is now supported (@webbeef, #34938)
- transferControlToOffscreen() is now supported (@webbeef, #34959)

Streams are a lot more useful now, with ReadableStreamBYOBReader now supporting read() (@Taym95, #35040), cancel(), close(), and releaseLock() (@Taym95, #34958).
Servo now passes 40.6% (+7.5pp) of enabled Shadow DOM tests, thanks to our landing support for the :host selector (@simonwuelker, #34870) and the <slot> element (@simonwuelker, #35013, #35177, #35191, #35221, #35137, #35222), plus improvements to event handling (@simonwuelker, #34788, #34884), script (@willypuzzle, #34787), style (@simonwuelker, @jdm, #35198, #35132), and the DOM tree (@simonwuelker, @Taym95, #34803, #34834, #34863, #34909, #35076).
Table layout is significantly better now, particularly in ‘table-layout: fixed’ (@Loirooriol, #35170), table sizing (@Loirooriol, @mrobinson, #34889, #34947, #35167), rowspan sizing (@mrobinson, @Loirooriol, #35095), interaction with floats (@Loirooriol, #35207), and ‘border-collapse’ layout (@Loirooriol, #34932, #34908, #35097, #35122, #35165) and painting (@Loirooriol, #34933, #35003, #35100, #35075, #35129, #35163).
As a result, Servo now passes 90.2% (+11.5pp) of enabled CSS tables tests, and of the tests that are in CSS 2, we now pass more than Blink and WebKit! We literally stood on the shoulders of giants here, because this would not have been possible without Blink’s robust table impl. Despite their age, tables are surprisingly underspecified, so we also needed to report several spec issues along the way (@Loirooriol).
Embedding
Servo aims to be an embeddable web engine, but so far it’s been a lot harder to embed Servo than it should be.
For one, configuring and starting Servo is complicated. We found that getting Servo running at all, even without wiring up input or handling resizes correctly, took over 200 lines of Rust code (@delan, @mrobinson, #35118). Embedders (apps) could only control Servo by sending and receiving a variety of “messages” and “events”, and simple questions like “what’s the current URL?” were impossible to answer without keeping track of extra state in the app.
Contrast this with WebKitGTK, where you can write a minimal kiosk app with a fully-functional webview in under 50 lines of C. To close that gap, we’ve started reworking our embedding API towards something more idiomatic and ergonomic, starting with the concept embedders care about most: the webview.
Our new webview API is controlled by calling methods on a WebView handle (@delan, @mrobinson, #35119, #35183, #35192), including navigation and user input. Handles will eventually represent the lifecycle of the webview itself; if you have one, the webview is valid, and if you drop them, the webview is destroyed.
Servo needs to call into the embedder too, and here we’ve started replacing the old EmbedderMsg API with a webview delegate (@delan, @mrobinson, #35211), much like the delegates in Apple’s WebKit API.
In Rust, a delegate is a trait
that the embedder can install its own impl
for.
Stay tuned for more on this next month!
Embedders can now intercept any request, not just navigation (@zhuhaichao518, #34961), and you can now identify the webview that caused an HTTP credentials prompt (@pewsheen, @mrobinson, #34808).
Other embedding improvements include:
- Adding a trait to allow for alternative rendering contexts that are better suited to certain applications (@dklassic, @wusyong, #35052, #34813, #34780)
- Simplifying types used by consumers of libservo (@delan, @mrobinson, #35156)
- Making it easier to build Servo without crown (@jdm, #35055)
Other changes
We’ve reworked Servo’s preferences system, making all prefs optional with reasonable defaults (@mrobinson, #34966, #34999, #34994). As a result:
- The names of all preferences have changed; see the Prefs docs for a list
- Embedders no longer need a
prefs.json
resource to get Servo running - Some debug options were converted to preferences (@mrobinson, #34998)
Devtools now highlights console.log() arguments according to their types (@simonwuelker, #34810).
Servo’s networking is more efficient now, with the ability to cancel fetches for navigation that contain redirects (@mrobinson, #34919) and cancel fetches for <video> and <media> when the document is unloaded (@mrobinson, #34883). Those changes also eliminate per-request IPC channels for navigation and cancellation respectively, and in the same vein, we’ve eliminated them for image loading too (@mrobinson, #35041).
We’ve continued splitting up our massive script crate (@jdm, #34359, #35157, #35169, #35172), which will eventually make Servo much faster to build.
A few crashes have been fixed, including when exiting Servo (@mukilan, #34917), when using the internal memory profiler (@jdm, #35058), and when running ResizeObserver callbacks (@willypuzzle, #35168).
For developers
We now run CI smoketests on OpenHarmony using a real device (@jschwe, @mukilan, #35006), increasing confidence in your changes beyond compile-time errors.
We’ve also tripled our self-hosted CI runner capacity (@delan, #34983, #35002), making concurrent Windows and macOS builds possible without falling back to the much slower GitHub-hosted runners.
Servo can’t yet run WebDriver-based tests on wpt.fyi, wpt.servo.org, or CI, because the servo
executor for the Web Platform Tests does not support testdriver.js.
servodriver
does, though, so we’ve started fixing test regressions with that executor with the goal of eventually switching to it (@jdm, #34957, #34997).
Donations
Thanks again for your generous support!
We are now receiving 3835 USD/month (−11.4% over December) in recurring donations.
With this money, we’ve been able to expand our capacity for self-hosted CI runners on Windows, Linux, and macOS builds, halving mach try
build times from over an hour to under 30 minutes!
Servo is also on thanks.dev, and already 21 GitHub users (+5 over December) that depend on Servo are sponsoring us there. If you use Servo libraries like url, html5ever, selectors, or cssparser, signing up for thanks.dev could be a good way for you (or your employer) to give back to the community.
As always, use of these funds will be decided transparently in the Technical Steering Committee. For more details, head to our Sponsorship page.
Conference talks
- Why Build a New Browser Engine in Rust? (slides) — Martin Robinson spoke about Servo’s unique benefits as a Rust-based browser and web engine, and how browser diversity can create a new renaissance for the web platform