June was Servo’s busiest month in years, with 349 pull requests landing in our nightly builds!
Servo now supports viewport meta tags (@shubhamg13, @xiaochengh, #35901), the exportparts attribute (@simonwuelker, #37345), the ‘::part()’ selector (@simonwuelker, #37307), and several new web API features:
- <script type=“importmap”> (@wusyong, @pewsheen, #37291, #37405, #37504, #37552, #37547, #37340)
- ImageBitmap (@tharkum, #37025, #37397, #37488, #37560, #37634)
- scroll events in the DOM (@PotatoCP, @Asun0204, #36687)
- the supports() method on HTMLScriptElement (@pewsheen, #37313)
- the lang() and id() functions in XPath (@vlindhol, #34594)
- the <hr size> attribute (@simonwuelker, #37211)
- barebones IndexedDB support, with
--pref dom_indexeddb_enabled
(@arihant2math, @rasviitanen, @jdm, #33044, #37652, #37653)
You can now use a screen reader to help you control servoshell’s browser UI (@jdm, #37519). Note that Servo’s webviews are not yet accessible to screen readers.

You can now call setTransform() with a dictionary on CanvasRenderingContext2D and CanvasPattern (@tharkum, #37692, #37731).

Abort handling on the web is a lot more viable now, with support for abort() and signal on AbortController (@gterzian, #37192, #37217), plus aborted, reason, and throwIfAborted() on AbortSignal (@gterzian, #37218, #37227, #37245).
Our experimental multiprocess mode (-M
/ --multiprocess
) now works on Windows (@wusyong, #37580).
We’ve fixed several bugs, notably including a bug in the encoding of HTML form submissions in non-Unicode documents (@simonwuelker, #37541), which single-handedly fixed over 97000 subtests in the Web Platform Tests.
Outreachy intern Jerens Lensun (@jerensl) is now working on improving linting in mach! Keep an eye out for his patches, and in the meantime, check out the blog post he wrote about his experiences.
Devtools
Servo’s devtools support is becoming more capable! We now have basic support for the Network tab (@uthmaniv, #37384, #37263, #37543, #37707), including listing requests and viewing Headers and Timings.
This work on our network inspector would not be possible without our Outreachy intern Usman Baba Yahaya (@uthmaniv)! Until next month, check out the blog post he wrote about his time so far.
In addition, our devtools are now compatible with Firefox 139 (@eerii, #37247), and we’ve landed some preliminary work towards supporting the Sources tab (@atbrakhi, @delan, #36774, #37456, #37197).

Performance
We’ve landed several improvements towards incremental layout, a broad class of optimisations that ensure that layout work is only done when something has changed and never done twice. That work is some subset of these five steps:
- Style, that is, calculating the styles for the DOM tree
- Box tree construction, taking the styled DOM tree as input
- Fragment tree construction, for pages, columns, and lines
- Stacking context tree construction, sorting it into CSS painting order
- Display list construction, yielding the input we send to WebRender
Servo can now skip display list construction when nothing would change (@mrobinson, @Loirooriol, #37186). This change is especially noticeable when moving the mouse cursor around on a page.
Script queries, like offsetParent and getBoundingClientRect(), read back information from style and layout. When answering script queries, we can often skip some steps that are not relevant, but three steps were previously unavoidable. Script queries can now skip style, box tree, and fragment tree updates when those are up to date (@mrobinson, @Loirooriol, #37677). This means some queries can now be answered without doing any work at all!
You can now change ‘transform’, ‘scale’, ‘rotate’, ‘translate’, and ‘perspective’ without a full layout in many cases (@Loirooriol, @mrobinson, #37380).
WebDriver
Work continues on our WebDriver server, which can be used to automate Servo and will also power our support for testdriver.js-based Web Platform Tests. We now better handle operations for switching contexts (@yezhizhen, @longvatrong111, #37685, #37632, #37411), sending input (@longvatrong111, @yezhizhen, @PotatoCP, #37484, #37624, #37403, #37260, #37423, #37224, #37393, #37153, #37095), inspecting the page (@yezhizhen, #37521, #37532, #37502, #37452, #37425, #37470), and working with shadow roots (@yezhizhen, @longvatrong111, #37546, #37578, #37280).
Want to try automating Servo with WebDriver? It’s so easy it fits in a blog post!
$ cargo new app
$ cd app
$ cargo add [email protected]
use std::{
error::Error, net::{Shutdown, TcpStream},
process::Command, thread::sleep, time::Duration,
};
use webdriver_client::{
Driver, HttpDriverBuilder, LocationStrategy,
messages::{ExecuteCmd, NewSessionCmd},
};
fn main() -> Result<(), Box<dyn Error>> {
// Run servoshell.
Command::new("/path/to/servo")
.args(["--webdriver", "about:blank"])
.spawn()?;
let driver = HttpDriverBuilder::default()
.url("http://127.0.0.1:7000")
.build()?;
let mut params = NewSessionCmd::default();
// Remove the unsupported `goog:chromeOptions` capability, which Servo rejects
// with a “Session not created due to invalid capabilities” error.
params.reset_always_match();
// Wait for the WebDriver server to start.
loop {
sleep(Duration::from_millis(250));
if let Ok(stream) = TcpStream::connect("127.0.0.1:7000") {
stream.shutdown(Shutdown::Both)?;
break;
}
}
// Connect to the WebDriver server and control Servo.
let session = driver.session(¶ms)?;
session.go("https://bucket.daz.cat/work/igalia/servo/webdriver-example/")?;
session.execute(ExecuteCmd {
script: "scrollBy(0,9001)".to_owned(),
args: vec![],
})?;
let diffie = session.find_element(
"#thread-diffie img",
LocationStrategy::Css,
)?;
diffie.click()?;
sleep(Duration::from_secs(1));
session.execute(ExecuteCmd {
script: "const h1 = document.querySelector('h1');
h1.innerHTML = 'hello from webdriver!';
scrollBy(0,300)".to_owned(),
args: vec![],
})?;
Ok(())
}

Donations
Thanks again for your generous support! We are now receiving 4464 USD/month (−2.8% over May) in recurring donations. This helps cover the cost of our self-hosted CI runners and one of our latest Outreachy interns!
Keep an eye out for further improvements to our CI system in the coming months, including dedicated benchmarking runners and ten-minute WPT builds, all thanks to your support.
Servo is also on thanks.dev, and already 25 GitHub users (same as May) 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.