{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreibasuy55my4qry4skxgp6ogym2wahgtuatlkg2enjnsegnv3zznfq",
"uri": "at://did:plc:qp37y62idugoomg4hj4hfukc/app.bsky.feed.post/3mn65kh2igm42"
},
"path": "/blog/2026/05/31/april-in-servo/",
"publishedAt": "2026-05-31T18:02:16.015Z",
"site": "https://servo.org",
"tags": [
"Servo 0.2.0",
"§ Security",
"the crates.io release",
"@lukewarlow",
"@mrobinson",
"43189",
"@simonwuelker",
"44246",
"@rayguo17",
"43208",
"@shubhamg13",
"40098",
"43715",
"@Loirooriol",
"43890",
"43878",
"@SimonSapin",
"44480",
"@TG199",
"44073",
"@jdm",
"44004",
"@niyabits",
"44159",
"44289",
"44272",
"@TimvdLippe",
"44461",
"@Taym95",
"43976",
"43861",
"@kkoyung",
"43703",
"43903",
"43926",
"@Messi002",
"43984",
"@SharanRP",
"43744",
"@yezhizhen",
"@CynthiaOketch",
"@nortti0",
"44055",
"44138",
"44514",
"@webbeef",
"43702",
"44341",
"Security",
"Work in progress",
"servoshell",
"For developers",
"Embedding API",
"More on the web platform",
"Performance and stability",
"44597",
"@yvt",
"28583",
"44002",
"43988",
"44038",
"44088",
"@officialasishkumar",
"44152",
"@simartin",
"44270",
"@Narfinger",
"43891",
"@arihant2math",
"44245",
"Preferences",
"dom_indexeddb_enabled",
"44283",
"Storage Standard",
"@gterzian",
"44374",
"43900",
"39009",
"44128",
"43901",
"44009",
"43914",
"44161",
"44183",
"44059",
"44215",
"42998",
"43805",
"@stevennovaryo",
"42204",
"44529",
"44511",
"43287",
"44432",
"44410",
"44194",
"44030",
"44039",
"44041",
"44075",
"44234",
"44250",
"44331",
"44390",
"44137",
"44293",
"44312",
"44347",
"@alice",
"@delan",
"42338",
"43558",
"44437",
"44438",
"44255",
"44473",
"44208",
"44198",
"44290",
"44335",
"44421",
"44452",
"44481",
"44585",
"44594",
"44375",
"44440",
"@rovertrack",
"43617",
"44343",
"@espy",
"43795",
"@jschwe",
"44278",
"44182",
"44327",
"42713",
"43872",
"43932",
"44223",
"@arabson99",
"43912",
"@atbrakhi",
"@eerii",
"44172",
"44173",
"44022",
"44233",
"44196",
"44181",
"44064",
"44023",
"44164",
"44369",
"44262",
"43792",
"43791",
"43981",
"@freyacodes",
"44142",
"44517",
"44462",
"44577",
"44459",
"44177",
"44135",
"dev container",
"our usual procedures",
"@sagudev",
"44126",
"44111",
"44162",
"44641",
"44109",
"in the book",
"Lix",
"Nix",
"NixOS page",
"44346",
"44010",
"@zhangxichang",
"44264",
"44591",
"‘servo’",
"Cargo’s rules for semver compatibility",
"‘servo-base’",
"‘servo-script’",
"44093",
"@mukilan",
"43972",
"44642",
"43182",
"43866",
"44086",
"43797",
"WebView",
"animating",
"@JavaDerg",
"44253",
"Servo",
"site_data_manager",
"@sabbCodes",
"44116",
"WebViewDelegate",
"43895",
"GamepadDelegate",
"load_request",
"@longvatrong111",
"43338",
"SiteDataManager",
"cookies_for_url_async",
"43794",
"cookies_for_url",
"CookieSource",
"44124",
"permanent cookies",
"clear_session_cookies",
"44166",
"ServoDelegate",
"load_web_resource",
"destination",
"referrer_url",
"WebResourceRequest",
"44493",
"Opts",
"temporary_storage",
"@janvarga",
"44433",
"WindowRenderingContext",
"new",
"SoftwareRenderingContext",
"44011",
"WebViewBuilder",
"ServoDelegate",
"PromptDialog",
"WebResourceLoad",
"WebXrRegistry",
"EXPERIMENTAL_PREFS",
"43892",
"43787",
"44171",
"43947",
"OutputOptions",
"DiagnosticsLogging",
"PrefValue",
"servo",
"opts",
"servo_config",
"43802",
"44397",
"43940",
"43899",
"43822",
"44496",
"43770",
"43799",
"44094",
"@Gae24",
"43632",
"43897",
"43989",
"@MuhammadMouostafa",
"@treetmitterglad",
"44282",
"43260",
"43882",
"43970",
"43798",
"43842",
"44029",
"44360",
"43859",
"44535",
"43700",
"@elomscansio",
"43741",
"44179",
"44042",
"43857",
"44420",
"43873",
"@RichardTjokroutomo",
"44061",
"43461",
"43807",
"44046",
"43627",
"@log101",
"44411",
"44357",
"43608",
"44367",
"@msub2",
"44155",
"44471",
"44199",
"43990",
"43753",
"44228",
"44243",
"44299",
"44474",
"44457",
"44551",
"44281",
"44550",
"@Veercodeprog",
"43674",
"43620",
"@nicoburns",
"44324",
"44031",
"44133",
"43746",
"43977",
"44035",
"44016",
"the ECMAScript spec",
"44120",
"44127",
"44117",
"44242",
"44443",
"44456",
"Two key components",
"43124",
"44074",
"43983",
"44037",
"43858",
"44364",
"42904",
"44231",
"44370",
"43974",
"44436",
"44227",
"44221",
"44303",
"44338",
"44428",
"44134",
"44008",
"44544",
"44271",
"44279",
"43826",
"44052",
"44139",
"@thebabalola",
"43844",
"44607",
"44435",
"44503",
"44386",
"44573",
"44581",
"44424",
"44203",
"44560",
"44024",
"43995",
"43846",
"@drasticactions",
"43933",
"u64",
"44079",
"43888",
"43930",
"44259",
"web storage features",
"43918",
"43949",
"44070",
"garbage collection",
"@willypuzzle",
"44119",
"44501",
"44513",
"44489",
"@nodelpit",
"43174",
"43524",
"43928",
"43943",
"43942",
"43944",
"43946",
"43952",
"43975",
"44018",
"44175",
"44241",
"44368",
"44406",
"44441",
"44422",
"44475",
"44478",
"44484",
"44476",
"44490",
"44477",
"44494",
"44497",
"44498",
"44495",
"44505",
"44506",
"44507",
"44508",
"44509",
"44510",
"44512",
"44482",
"44527",
"44528",
"44531",
"44534",
"44542",
"44533",
"44543",
"44553",
"44547",
"44563",
"44562",
"44565",
"44558",
"44583",
"44606",
"44605",
"44608",
"44602",
"44584",
"44620",
"44590",
"44254",
"44628",
"44629",
"44638",
"44626",
"44081",
"@Skgland",
"@foresterre",
"@StaySafe020",
"43772",
"44006",
"43860",
"44121",
"44160",
"43884",
"44154",
"44569",
"43939",
"44003",
"44110",
"44122",
"43824",
"44635",
"44103",
"43978",
"44092",
"44114",
"44277",
"44454",
"44274",
"44237",
"44232",
"44167",
"44214",
"43820",
"43825",
"43810",
"43838",
"43841",
"43847",
"43875",
"43876",
"43889",
"43893",
"43896",
"43881",
"43906",
"43913",
"43908",
"43917",
"43910",
"43921",
"43924",
"43925",
"43907",
"43923",
"43916",
"43909",
"43911",
"43957",
"43969",
"43967",
"43915",
"43954",
"43963",
"43959",
"43955",
"44067",
"44068",
"44071",
"44084",
"44265",
"44115",
"44358",
"43848",
"speedy",
"CI",
"and",
"benchmarking",
"servers",
"Outreachy interns",
"maintainer work",
"thanks.dev",
"url",
"html5ever",
"selectors",
"cssparser",
"sponsorship tiers",
"funding request process",
"servo/project#187",
"Sponsorship page",
"@layer",
"@keyframes",
"@property"
],
"textContent": "Servo 0.2.0 contains all of the changes we landed in April, which came out to yet another record **534 commits** (March: 530). For security fixes, see § Security.\n\n**Note:** the GitHub release is available now, but the crates.io release is not yet complete. We expect to publish it some time **next week**.\n\nWe’ve shipped several new web platform features:\n\n * **< select multiple>** (@lukewarlow, @mrobinson, #43189)\n * **< template shadowrootslotassignment>** (@simonwuelker, #44246)\n * **< video>** playback on OpenHarmony (@rayguo17, #43208)\n * **‘minimum-scale’** and **‘maximum-scale’** values in **< meta name=viewport>** (@shubhamg13, #40098, #43715)\n * **‘color-mix()’** with **any number of <color> values** (@Loirooriol, #43890)\n * **‘ &::before’** and **‘ &::after’** in **‘::details-content’** (@Loirooriol, #43878)\n * **‘revert-rule’** (@Loirooriol, #43878)\n * **‘tab-size’** (@mrobinson, @SimonSapin, #44480)\n * **‘text-align: match-parent’** (@TG199, #44073)\n * **new Worker()** with **blob URLs** (@jdm, #44004)\n * **getContext(`\"webgl\"`)** on **OffscreenCanvas** (@niyabits, #44159)\n * the **detail** property on **PerformanceMark** and **PerformanceMeasure** (@shubhamg13, #44289, #44272)\n\n\n\nPlus a bunch of new DOM APIs:\n\n * **‘selectionchange’** events on <input> and <textarea> (@TimvdLippe, #44461)\n * **StorageManager** , in experimental mode (@Taym95, #43976)\n * **activeElement** on **Document** and **ShadowRoot** (@mrobinson, #43861)\n * **crypto.subtle.supports()** (@kkoyung, #43703) – Servo is the first major browser engine to support this!\n * **cellPadding** , **cellSpacing** , and **align** properties on **HTMLTableElement** (@mrobinson, #43903) – previously supported in HTML only\n * **relatedTarget** on **‘focus’** and **‘blur’** events (@mrobinson, #43926)\n * **transferFromImageBitmap()** on **ImageBitmapRenderingContext** (@Messi002, #43984)\n\n\n\nServo’s support for text in **Chinese** , **Japanese** , and **Korean** languages has improved, with correct wrapping in the layout engine (@SharanRP, #43744), and CJK fonts now enabled in servoshell’s browser UI on Windows, Linux, and FreeBSD (@yezhizhen, @CynthiaOketch, @nortti0, #44055, #44138, #44514).\n\nNavigating to a **JSON file** as the top-level document now renders the JSON with an **interactive pretty-printer** (@webbeef, @TimvdLippe, #43702).\n\nApril was a big milestone for Servo, with some automated tests failing because they had hard-coded cookie expiry dates set to April 2016 plus ten years. Surprise! We’re still here. Here’s to the next 100 years of Servo (@jdm, #44341).\n\nThis is another big update, so here’s an outline:\n\n * Security\n\n * Work in progress\n\n * servoshell\n\n * For developers\n\n * Embedding API\n\n * More on the web platform\n\n * Performance and stability\n\n\n\n\n## Security \n\n**CryptoKey** now zeroes buffers containing key material after use (@kkoyung, #44597).\n\nWith only a few exceptions, you can only access DOM APIs in another document if that document is in the **same origin**. But if that document is in the same _site_ with a different port number, Servo currently allows these accesses even though it shouldn’t. We’ve fixed some (but not all) of these incorrect accesses, specifically those that involve binding a Window or Location method in this document with a `this` from the other document (@yvt, @jdm, #28583).\n\nWe’ve fixed a bug where **localStorage** and **sessionStorage** were usable in **sandboxed <iframe>** and shared with every other sandboxed <iframe>, rather than throwing SecurityError (@Taym95, #44002).\n\nWe’ve fixed a bug where **localStorage** and **sessionStorage** were shared between all **< iframe srcdoc> documents**, rather than isolated using the origin of the containing document (@niyabits, #43988, #44038).\n\nWe’ve fixed a bug where **IndexedDB** was usable in **sandboxed <iframe>** and **data: URL web workers** (@Taym95, #44088).\n\nWe’ve fixed a bug where pages in some **IP address origins** can evict cookies from other IP address origins (@officialasishkumar, #44152). Only evicting cookies was possible, not reading or writing them.\n\nWe’ve fixed an **out-of-bounds memory read** in **texImage3D()** on **WebGL2RenderingContext** (@simartin, #44270), and fixed some undefined behaviour in servoshell’s signal handler (@Narfinger, #43891).\n\n## Work in progress \n\n**IndexedDB** is now enabled in servoshell’s experimental mode (@arihant2math, #44245). As always, embedders can enable it with Preferences::dom_indexeddb_enabled (@arihant2math, #44245, #44283).\n\nIndexedDB now uses Servo’s new **“client storage”** system, which is based on the Storage Standard and will allow us to have a unified on-disk format and quota management for all web platform features that persistently store data (@gterzian, #44374, #43900). We’ve also made key range queries more efficient (@arihant2math, #39009), landed improvements to IDBDatabase, IDBObjectStore, IDBCursor, IDBKeyRange, IDBRequest, and to the handling of transactions, keys, values, and exceptions (@Taym95, #44128, #43901, #44009, #43914, #44161, #44183, #44059, #44215, #42998, #43805).\n\nWe’ve made more progress on the **IntersectionObserver API** , under `--pref dom_intersection_observer_enabled` (@stevennovaryo, @jdm, #42204).\n\nWe’re continuing to implement **document.execCommand()** for **rich text editing** (@TimvdLippe, #44529), under `--pref dom_exec_command_enabled`. This release adds support for the **‘bold’** , **‘fontName’** , **‘fontSize’** , **‘italic’** , **‘strikethrough’** , and **‘underline’** commands (@TimvdLippe, @jdm, @mrobinson, #44511, #43287, #44432, #44410, #44194, #44030, #44039, #44041, #44075, #44234, #44250, #44331, #44390, #44137, #44293, #44312, #44347).\n\nAll of the features above are enabled in servoshell’s experimental mode.\n\nServo can now build a very basic **accessibility tree** for web contents, under `--pref accessibility_enabled` (@alice, @delan, @lukewarlow, #42338, #43558, #44437, #44438). This includes text runs, plus nine other non-interactive accessibility roles (@alice, @delan, #44255). We’ve also fixed a crash when reloading pages with accessibility enabled (@alice, #44473), and made accessibility tree updates more efficient (@alice, #44208).\n\nWe’ve started implementing the **Sanitizer API** , under `--pref dom_sanitizer_enabled` (@kkoyung, #44198, #44290, #44335, #44421, #44452, #44481, #44585, #44594).\n\nWe’ve also started implementing **SharedWorker** , under `--pref dom_sharedworker_enabled` (@Taym95, #44375, #44440).\n\nWe’re working on the **WakeLock API** too, under `--pref dom_wakelock_enabled` (@TG199, @rovertrack, #43617, #44343).\n\n## servoshell \n\nservoshell for Android now has a **revamped browser UI** , including a new **history view** (@espy, #43795), the **apk is 30% smaller** (@jschwe, #44278, #44182), and we’ve fixed the black screen bug when closing settings or switching back from another app (@yezhizhen, #44327). You can now close tabs on OpenHarmony too (@Narfinger, #42713).\n\nAs for servoshell on desktop platforms, we’ve fixed some focus- and IME-related bugs (@mrobinson, #43872, #43932), and on Windows, we now install a normal shortcut without the strange behaviour of an “advertised” shortcut (@yezhizhen, #44223).\n\n## For developers \n\nWhen using the **Inspector** tab in the Firefox **DevTools** , the **Rules** panel now includes declarations in **‘@layer’ rules** (@arabson99, #43912).\n\nWhen **logging expressions** in the **Console** tab, and when **hovering over symbols** in the **Debugger** tab, you can now get more information about the contents of functions, arrays, objects, and other values (@atbrakhi, @eerii, #44172, #44173, #44022, #44233, #44196, #44181, #44064, #44023, #44164, #44369, #44262).\n\nWhen using the **Debugger** tab, you can now use the **Scopes** panel to inspect local and global variables (@eerii, @atbrakhi, #43792, #43791), you can now debug **web worker** scripts (@atbrakhi, #43981), and we’ve started implementing **blackboxing** , aka the **Ignore source** button (@freyacodes, #44142).\n\nWe’ve also landed some initial support for the **Style Editor** tab (@rovertrack, #44517, #44462).\n\nWe’re working towards re-enabling our automated DevTools tests in CI, which should make the feature more reliable (@freyacodes, #44577), and we’ve landed a small build reproducibility fix too (@jschwe, #44459).\n\nFor developers of Servo itself, please note that the **Cargo ‘release’ profile** is no longer `#[cfg(debug_assertions)]` (@jschwe, @mrobinson, #44177). If you’ve been using ‘release’ as a “faster ‘debug’ with assertions” build locally, consider switching to ‘checked-release’ or ‘medium’.\n\nThe pull request template has been updated (@mrobinson, #44135). **‘Testing’** and **‘Fixes’** should go at the _bottom_ of the PR description, and **‘Testing’** is about automated tests, not how you tested the PR locally.\n\nWe’ve made more progress on the new dev container, which will provide an alternative to our usual procedures for setting up a Servo build environment (@jschwe, @sagudev, #44126, #44111, #44162, #44641, #44109). Keep an eye out for that in the book!\n\nIn the meantime, did you know that you can use Lix or Nix to build Servo on Linux with a lot less hassle, _even if_ you’re not using NixOS? For now at least, head to the NixOS page in the book to learn more. We’ve also fixed a regression that made `--debug-mozjs` and `MOZJS_FROM_SOURCE` builds take much longer to complete on Linux when not using Nix (@jschwe, #44346).\n\nWe’ve fixed building Servo with the **‘jitspew’ feature** in mozjs, allowing you to set **IONFLAGS** to enable JIT logging (@simonwuelker, #44010). We’ve also fixed build issues on Windows and FreeBSD (@zhangxichang, @mrobinson, #44264, #44591).\n\n## Embedding API \n\nWith this second monthly release of the Servo library, we have some quick notes about **API stability** and **semver compatibility** :\n\n * **The ‘servo’ package** follows Cargo’s rules for semver compatibility. 0.1.1 is compatible with version 0.1.0, but 0.2.0 is a breaking update.\n\n * Until we integrate semver analysis into our release process, each monthly release will have a breaking version number, while non-breaking version numbers may be used for LTS updates.\n\n * In general, **dependencies of ‘servo’** , like ‘servo-base’ and ‘servo-script’, **do not use semver**. Any release may include breaking changes.\n\n\n\n\nWe’ve fixed a **build failure** affecting embedders with a **new or updated Cargo.lock** (@jschwe, #44093), and landed several other changes to help us with the Servo library release process (@jschwe, @mukilan, #43972, #44642, #43182, #43866, #44086, #43797).\n\nBreaking changes:\n\n * WebView::animating now takes `&self` instead of `self`, so you can call it without cloning the handle (@JavaDerg, #44253)\n\n * Servo::site_data_manager now returns `&SiteDataManager` instead of `Ref<'_, SiteDataManager>` (@sabbCodes, #44116)\n\n * WebViewDelegate::`play_gamepad_haptic_effect` and `stop_gamepad_haptic_effect` have been removed (@mrobinson, #43895), but they have not worked since February 2026 – use GamepadDelegate instead\n\n\n\n\nYou can now load a URL with **custom request headers** by calling WebView::load_request (@Narfinger, @longvatrong111, @mrobinson, #43338).\n\nYou can now **retrieve cookies asynchronously** by calling SiteDataManager::cookies_for_url_async (@longvatrong111, #43794).\n\nThe synchronous version of that method, SiteDataManager::cookies_for_url, was previously not callable because CookieSource was not exposed to the public API, but we’ve fixed that now (@TG199, #44124).\n\nYou can now **clear session cookies** without clearing permanent cookies by calling SiteDataManager::clear_session_cookies (@longvatrong111, #44166).\n\nWhen **intercepting requests** with ServoDelegate:: and WebViewDelegate::load_web_resource, we now include a destination and referrer_url in the WebResourceRequest, which can be helpful if you’re implementing **ad blocking** (@webbeef, #44493).\n\nYou can configure Servo to **write all of its storage to a unique directory** for that session by enabling Opts::temporary_storage (@janvarga, #44433). Note that these unique directories currently persist after Servo exits, so it’s an isolation feature, not a privacy feature.\n\nWindowRenderingContext::new and SoftwareRenderingContext::new now return an error if the given `size` is less than 1x1 (@freyacodes, @mrobinson, #44011).\n\nWe’ve improved our API docs for WebView, WebViewBuilder, WebViewDelegate, ServoDelegate, PromptDialog, WebResourceLoad, WebXrRegistry, Preferences, and servoshell’s EXPERIMENTAL_PREFS (@simonwuelker, @TG199, @sabbCodes, @jdm, @rovertrack, #43892, #43787, #44171, #43947).\n\nWe’ve also improved our API docs for Opts, OutputOptions, DiagnosticsLogging, PrefValue, servo::opts, and servo_config (@mukilan, #43802).\n\n## More on the web platform \n\n**`Tab` navigation** now works across **< iframe>** boundaries (@mrobinson, #44397), and **`Ctrl` +`Backspace`** (or **`⌥`` ⌫`**) now **deletes a whole word** in input fields (@mrobinson, #43940).\n\n**Tab characters** are now rendered correctly in **< pre>** (and other elements with **‘white-space: pre’**), with proper tab stops (@mrobinson, @SimonSapin, #44480). **Spaces** are now rendered correctly in **2D <canvas>**, instead of twice as wide as they should be (@mrobinson, #43899).\n\n**< a href>** now correctly resolves the URL with the page encoding (@sabbCodes, #43822).\n\nWe’ve improved the default appearance of **< input type=file>** (@sabbCodes, #44496) and **< textarea placeholder>** (@mrobinson, #43770).\n\nAll **keyboard events** , **mouse events** , **wheel events** , and **pointer events** , other than **‘pointerenter’** and **‘pointerleave’** , now **bubble out of shadow roots** (@simonwuelker, @webbeef, #43799, #44094). **‘error’ events** on **Window** now report the correct **filename** (**source** in **onerror**) and **lineno** (@Gae24, #43632).\n\n**console.log()** and friends now support **printf-style formatting directives** , although for now `%c` is ignored (@TG199, #43897).\n\n**file: URLs** are now considered **secure contexts** , so they can now use features like **crypto.subtle** and **crypto.randomUUID** (@simonwuelker, #43989).\n\n**Exception messages** have improved in Location, StaticRange, and the HTMLElement family of types (@arihant2math, @MuhammadMouostafa, @treetmitterglad, #44282, #43260, #43882).\n\nWe’ve improved the conformance of **fetch algorithms** (@yezhizhen, #43970, #43798), **focus** and **tab navigation** (@mrobinson, #43842, #44029, #44360, #43859, #44535), **form submission** (@TG199, #43700), **JS modules** (@elomscansio, @Gae24, #43741, #44179, #44042), **page navigation** (@TimvdLippe, #43857), **< svg viewBox>** (@yezhizhen, #44420), **‘attr()’** (@Loirooriol, #43878), **‘:focus’** (@mrobinson, #43873), **‘font’** (@RichardTjokroutomo, #44061), **‘@keyframes’** (@simonwuelker, #43461), **‘@property’** (@Loirooriol, #43878), **‘load’** events (@jdm, @arabson99, #43807, #44046), **fetchLater()** (@TimvdLippe, #43627), **axes** and **buttons** on **Gamepad** (@log101, @rovertrack, #44411, #44357), **copyTexImage2D()** on **WebGLRenderingContext** (@simartin, @mrobinson, #43608), **texImage3D()** on **WebGL2RenderingContext** (@simartin, #44367), **environmentBlendMode** on **XRSession** (@msub2, #44155), **mark()** and **measure()** on **Performance** (@shubhamg13, @simonwuelker, #44471, #44199, #43990, #43753), and **PerformanceResourceTiming** (@shubhamg13, #44228).\n\nWe’ve fixed bugs related to **console logging** (@sabbCodes, #44243), **‘animation’** (@mrobinson, #44299), **‘box-shadow’** (@yezhizhen, #44474, #44457), **‘display: contents’** (@Loirooriol, @mrobinson, #44551, #44299), **‘display: inline-flex’** (@SimonSapin, #44281), **‘display: table-cell’** (@Loirooriol, #44550), **‘display: table-row-group’** (@Veercodeprog, #43674), **‘overflow-x: clip’** and **‘overflow-y: clip’** (@Messi002, #43620), **‘position: absolute’** on grid items (@nicoburns, #44324), **‘word-spacing: <percentage>’** (@sabbCodes, #44031), **removeChild()** on **Document** (@rovertrack, #44133), and **URL.revokeObjectURL()** (@simonwuelker, @jdm, #43746, #43977, #44035).\n\n## Performance and stability \n\nWe’ve fixed some big inefficiencies in Servo. **appendChild()** with nested shadow roots is no longer O(2n) (@yezhizhen, @webbeef, #44016), and we’ve halved the time it takes to load the ECMAScript spec by fixing the O(whole DOM tree) processing of **‘id’** and **‘name’ attributes** (@simonwuelker, #44120, #44127, #44117).\n\nServo makes its **first TLS connection** in each session **30–60 ms faster** (@jschwe, #44242), and we’ve instrumented the Servo and servoshell startup processes to find more opportunities for optimisation (@jschwe, #44443, #44456).\n\nLike most browser engines, Servo is a multi-threaded (and sometimes multi-process) system requiring a great deal of IPC messages to keep everything connected. Two key components of this system are the **constellation** thread, which manages the engine as a whole, and the **script threads** (or web processes), which render the web pages. Sending these messages can be expensive though, so to **reduce unnecessary IPC traffic** , we’ve landed an optimisation that allows script threads to selectively receive only the relevant messages from the constellation (@webbeef, #43124).\n\nWe’ve reduced the **memory usage** of each **Attr** , **Text** , and **CharacterData** node in the DOM by 16 bytes (@mrobinson, @Loirooriol, #44074), and **fixed a memory leak** when deleting **< video controls>** or **< audio controls>** (@Messi002, #43983).\n\nOur **about:memory** page is more accurate now too, with new tracking of **libc memory allocations** on macOS, improved tracking of libc memory allocations on Linux (@jschwe, #44037), and more accurate tracking of PathBuf and types in `tokio`, `http`, `data_url`, and `urlpattern` (@Narfinger, #43858).\n\nLess memory usage isn’t always better in browser engines though, because there are many kinds of caches and other optimisations we can do to make browsing the web faster, at the expense of increased memory usage. For example, we can greatly speed up **prototype checks** for DOM objects by storing a number in each object that identifies the concrete type, at the expense of making each DOM object 64 bits larger (@webbeef, #44364).\n\nLayout can now **reuse fragments** in later reflows, in many cases that involve block layout or ‘position: absolute’ (@mrobinson, @lukewarlow, @Loirooriol, #42904, #44231). We’re also working on **reusing shaping results** in later reflows, and making inline layout more efficient (@mrobinson, #44370, #43974, #44436).\n\nWe’ve landed several changes that should reduce the **binary size** of Servo (@rovertrack, @mrobinson, @nicoburns, @Narfinger, #44227, #44221, #44303, #44338, #44428, #44134).\n\nWe’ve also reduced clones, allocations, borrow checks, GC rooting steps, and other operations in many parts of Servo (@rovertrack, @Narfinger, @Loirooriol, @yezhizhen, @simonwuelker, #44008, #44544, #44271, #44279, #43826, #44052, #44139).\n\nSeveral crashes have been fixed:\n\n * in compressedTexSubImage2D() on WebGLRenderingContext (@thebabalola, #44050)\n * in console.log() (@thebabalola, #43844)\n * in getData() on DataTransfer (@SimonSapin, #44607)\n * in remove() on Element (@SimonSapin, #44435)\n * in replaceWith() on Element (@yezhizhen, #44503)\n * in `--debug-mozjs` builds (@jdm, #44386, #44573, #44581)\n * in flex and grid layout (@mrobinson, @nicoburns, #44424, #44203)\n * in layout queries like `offsetHeight` (@mrobinson, #44560)\n * in the devtools Debugger tab, when stepping and when inspecting nested values (@atbrakhi, @eerii, #44024, #43995)\n * when removing <colgroup> from the DOM (@Loirooriol, #43846)\n * when running garbage collection (@drasticactions, #43933)\n * when running servoshell with a u64 `--pref` (@yezhizhen, #44079)\n * when shadow roots are deeply nested, or when calling attachShadow() removes elements from the flat tree (@yezhizhen, @mrobinson, #43888, #43930, #44259)\n * when web storage features fail to write to disk or encounter SQLite errors (@arihant2math, @sabbCodes, #43918, #43949)\n\n\n\nWe fixed a crash in servoshell when pressing keys like Ctrl+2 or ⌘2 with not enough tabs open (@mrobinson, #44070).\n\n**DOM data structures** (`#[dom_struct]`) can refer to one another, with the help of garbage collection. But when DOM objects are being destroyed, those references can become invalid for a brief moment, depending on the order the GC finalizers run in. This can be unsound if those references are accessed, which is a very easy mistake to make if the type has an `impl Drop`. To help prevent that class of bug, we’re reworking our DOM types so that none of them have `#[dom_struct]` and `impl Drop` at the same time (@willypuzzle, #44119, #44501, #44513).\n\nWe’ve improved our static analysis for GC rooting (@officialasishkumar, #44489), and we’ve continued our long-running effort to **use the Rust type system** to make certain kinds of dynamic borrow failures impossible (@sagudev, @TimvdLippe, @Narfinger, @elomscansio, @Gae24, @rovertrack, @yezhizhen, @nodelpit, #43174, #43524, #43928, #43943, #43942, #43944, #43946, #43952, #43975, #44018, #44175, #44241, #44368, #44406, #44441, #44422, #44475, #44478, #44484, #44476, #44490, #44477, #44494, #44497, #44498, #44495, #44505, #44506, #44507, #44508, #44509, #44510, #44512, #44482, #44527, #44528, #44531, #44534, #44542, #44533, #44543, #44553, #44547, #44563, #44562, #44565, #44558, #44583, #44606, #44605, #44608, #44602, #44584, #44620, #44590, #44254, #44628, #44629, #44638, #44626, #44081).\n\nThanks to a wide range of people, we’ve also landed a bunch of cleanups and refactors (@delan, @alice, @Skgland, @atbrakhi, @eerii, @sabbCodes, @jdm, @thebabalola, @CynthiaOketch, @kkoyung, @TimvdLippe, @rovertrack, @webbeef, @arabson99, @yezhizhen, @simonwuelker, @mrobinson, @nicoburns, @longvatrong111, @niyabits, @treetmitterglad, @foresterre, @mukilan, @elomscansio, @freyacodes, @StaySafe020, @TG199, #43772, #44006, #43860, #44121, #44160, #43884, #44154, #44569, #43939, #44003, #44110, #44122, #43824, #44635, #44103, #43978, #44092, #44114, #44277, #44454, #44274, #44237, #44232, #44167, #44214, #43820, #43825, #43810, #43838, #43841, #43847, #43875, #43876, #43889, #43893, #43896, #43881, #43906, #43913, #43908, #43917, #43910, #43921, #43924, #43925, #43907, #43923, #43916, #43909, #43911, #43957, #43969, #43967, #43915, #43954, #43963, #43959, #43955, #44067, #44068, #44071, #44084, #44265, #44115, #44358, #43848).\n\n## Donations \n\nThanks again for your generous support! We are now receiving **7349 USD/month** (+2.5% from March) in recurring donations. This helps us cover the cost of our **speedy CI and benchmarking servers** , one of our latest **Outreachy interns** , and funding **maintainer work** that helps more people contribute to Servo.\n\nServo is also on thanks.dev, and already **33 GitHub users** (−4 from March) 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.\n\nWe now have sponsorship tiers that allow you or your organisation to donate to the Servo project with public acknowlegement of your support. If you’re interested in this kind of sponsorship, please contact us at join@servo.org.\n\n**7349** USD/month\n\n**10000**\n\nUse of donations is decided transparently via the Technical Steering Committee’s public **funding request process** , and active proposals are tracked in servo/project#187. For more details, head to our Sponsorship page.",
"title": "April in Servo: new Android UI, focus, forms, security fixes, and more!",
"updatedAt": "2026-05-31T00:00:00.000Z"
}