{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreidtnqdbyhcxcco7irtiutvzabeid6bro75xcxiuu5undyomoaemqy",
    "uri": "at://did:plc:qp37y62idugoomg4hj4hfukc/app.bsky.feed.post/3mkpdxugj75b2"
  },
  "path": "/blog/2026/04/30/march-in-servo/",
  "publishedAt": "2026-04-30T09:56:49.372Z",
  "site": "https://servo.org",
  "tags": [
    "Servo 0.1.0",
    "our first ever release on crates.io",
    "§ Security",
    "@mrobinson",
    "@Loirooriol",
    "42952",
    "43019",
    "43058",
    "43246",
    "43267",
    "43067",
    "43031",
    "43144",
    "43434",
    "43322",
    "@BudiArb",
    "@rayguo17",
    "41562",
    "@TimvdLippe",
    "43150",
    "43583",
    "43539",
    "43708",
    "43630",
    "@minghuaw",
    "@xiaochengh",
    "43027",
    "@stevennovaryo",
    "43053",
    "@lukewarlow",
    "@AlexVasiluta",
    "43498",
    "43666",
    "@niyabits",
    "43515",
    "43111",
    "43045",
    "<system-color>",
    "@longvatrong111",
    "42529",
    "43105",
    "43107",
    "<step-position>",
    "@yezhizhen",
    "43061",
    "43190",
    "41238",
    "@simonwuelker",
    "42989",
    "@jakubadamw",
    "43017",
    "@shubhamg13",
    "42901",
    "42949",
    "@kkoyung",
    "43551",
    "@Taym95",
    "43073",
    "43093",
    "43106",
    "43115",
    "@jschwe",
    "42958",
    "User­Content­Manager",
    "add­_script",
    "43573",
    "@simartin",
    "43320",
    "42912",
    "After a long effort",
    "@valpackett",
    "@dlrobertson",
    "@nortti0",
    "@sagudev",
    "43116",
    "43134",
    "44601",
    "crates.io",
    "43141",
    "43180",
    "43165",
    "@delan",
    "43170",
    "43458",
    "43463",
    "43459",
    "@StaySafe020",
    "43078",
    "43264",
    "43451",
    "43457",
    "43654",
    "@webbeef",
    "42916",
    "43243",
    "43263",
    "43516",
    "43526",
    "43552",
    "43615",
    "43622",
    "43273",
    "43092",
    "embedding Servo",
    "Security",
    "Work in progress",
    "For developers",
    "Embedding and automation",
    "More on the web platform",
    "Performance and stability",
    "43775",
    "43773",
    "43438",
    "43367",
    "43645",
    "43483",
    "@elomscansio",
    "43063",
    "@dyegoaurelio",
    "43216",
    "43652",
    "@arihant2math",
    "@gterzian",
    "@jerensl",
    "42139",
    "42727",
    "43096",
    "43041",
    "42451",
    "43721",
    "43754",
    "42786",
    "42251",
    "43177",
    "43087",
    "43028",
    "43016",
    "43082",
    "Font Loading API",
    "43286",
    "43281",
    "breaking change",
    "@alice",
    "43029",
    "43012",
    "43013",
    "43556",
    "@Gae24",
    "42964",
    "43353",
    "Web Bluetooth API",
    "btleplug",
    "43529",
    "43581",
    "Web Animations API",
    "43711",
    "async parser",
    "42930",
    "42959",
    "37418",
    "@CynthiaOketch",
    "43659",
    "@brentschroeter",
    "@eerii",
    "43026",
    "43153",
    "@SharanRP",
    "43361",
    "43492",
    "@atbrakhi",
    "42907",
    "43040",
    "43042",
    "43135",
    "43166",
    "43167",
    "43232",
    "43015",
    "43039",
    "43319",
    "43356",
    "43456",
    "42996",
    "42936",
    "42994",
    "43230",
    "43236",
    "43472",
    "mach",
    "42888",
    "dev container",
    "our usual procedures",
    "43127",
    "43131",
    "43139",
    "Servo",
    "WebView",
    "set­_accessibility­_active()",
    "adjust­_pinch­_zoom()",
    "pinch­_zoom()",
    "@chrisduerr",
    "43228",
    "WebViewBuilder",
    "delegate()",
    "clipboard­_delegate()",
    "gamepad­_delegate()",
    "43205",
    "43233",
    "WebViewDelegate",
    "show­_bluetooth­_device­_dialog()",
    "Bluetooth­Device­Selection­Request",
    "43580",
    "GamepadDelegate",
    "EventLoopWaker",
    "wake",
    "43250",
    "Opts",
    "DiagnosticsLogging",
    "progressive­_web­_metrics",
    "43209",
    "43207",
    "43206",
    "UserContentManager",
    "add­_stylesheet()",
    "SiteDataManager",
    "cookies­_for­_url()",
    "set­_cookie­_for­_url()",
    "43600",
    "ClipboardDelegate",
    "StringRequest",
    "@jdm",
    "43203",
    "43261",
    "EmbedderControlId",
    "InputMethodControl",
    "id()",
    "43248",
    "PixelFormat",
    "Debug",
    "43249",
    "ServoBuilder",
    "RenderingContext",
    "43229",
    "EmbedderControlRequest",
    "EmbedderControlResponse",
    "SimpleDialogRequest",
    "AlertResponse",
    "ConfirmResponse",
    "PromptResponse",
    "EmbedderMsg",
    "@mukilan",
    "43564",
    "ResourceReaderMethods",
    "43769",
    "servo",
    "input­_events",
    "43681",
    "WheelDelta",
    "43210",
    "actions",
    "43202",
    "43169",
    "43262",
    "43275",
    "43301",
    "42946",
    "43076",
    "43690",
    "a spec patch",
    "43014",
    "43126",
    "43128",
    "configure or disable",
    "43238",
    "43436",
    "@freyacodes",
    "43247",
    "42218",
    "43350",
    "captured",
    "42987",
    "43811",
    "43343",
    "@RichardTjokroutomo",
    "43447",
    "43125",
    "do nothing at all",
    "many",
    "bugs",
    "over",
    "the",
    "years",
    "43496",
    "a massive special case",
    "many quirks",
    "its own big edge cases",
    "@pylbrecht",
    "40365",
    "43449",
    "42736",
    "42771",
    "@abdelrahman1234567",
    "38773",
    "43178",
    "43175",
    "43186",
    "43132",
    "43201",
    "43485",
    "@jayant911",
    "@Veercodeprog",
    "@sabbCodes",
    "43521",
    "43554",
    "43572",
    "43537",
    "43634",
    "43588",
    "@nicoburns",
    "42118",
    "42566",
    "@Messi002",
    "43603",
    "42961",
    "42935",
    "43151",
    "42149",
    "42833",
    "42975",
    "43475",
    "43585",
    "42883",
    "43103",
    "43043",
    "43582",
    "42931",
    "@mishop-15",
    "42179",
    "42984",
    "43315",
    "43533",
    "43519",
    "43329",
    "43341",
    "43046",
    "42991",
    "@xZaisk",
    "@eyupcanakman",
    "43191",
    "43323",
    "43101",
    "43560",
    "43523",
    "43431",
    "42960",
    "43368",
    "43732",
    "43454",
    "42926",
    "43218",
    "@bruno-j-nicoletti",
    "43213",
    "43722",
    "43231",
    "@yoursanonymous",
    "43084",
    "42666",
    "spec",
    "issues",
    "counters",
    "43520",
    "43610",
    "43500",
    "43499",
    "43502",
    "43518",
    "this page on docs.rs",
    "43074",
    "43138",
    "43056",
    "42798",
    "42923",
    "43382",
    "43595",
    "43653",
    "@Narfinger",
    "43337",
    "42781",
    "42978",
    "43476",
    "42927",
    "update",
    "42077",
    "43309",
    "42966",
    "@TG199",
    "43212",
    "43055",
    "43066",
    "43304",
    "43452",
    "43717",
    "43780",
    "43088",
    "43226",
    "garbage collection",
    "@willypuzzle",
    "42937",
    "42982",
    "43018",
    "43071",
    "43222",
    "43288",
    "43544",
    "43563",
    "43631",
    "43381",
    "42976",
    "42963",
    "43487",
    "@rogerkorantenng",
    "43501",
    "43133",
    "43470",
    "@Tarmil",
    "42739",
    "@Uiniel",
    "@PuercoPop",
    "@arabson99",
    "42957",
    "43108",
    "43130",
    "43215",
    "43183",
    "43219",
    "43245",
    "43220",
    "43252",
    "43268",
    "43184",
    "43277",
    "43278",
    "43284",
    "43302",
    "43312",
    "43348",
    "43327",
    "43362",
    "43365",
    "43383",
    "43432",
    "43259",
    "43439",
    "43473",
    "43481",
    "43480",
    "43479",
    "43525",
    "43535",
    "43543",
    "43549",
    "43570",
    "43571",
    "43569",
    "43579",
    "43584",
    "43657",
    "43713",
    "43646",
    "43276",
    "43285",
    "43532",
    "43778",
    "43771",
    "43566",
    "43567",
    "43587",
    "43140",
    "43316",
    "@saydmateen",
    "43614",
    "43641",
    "43619",
    "43642",
    "43623",
    "43656",
    "43644",
    "43672",
    "43664",
    "43676",
    "43684",
    "43679",
    "43678",
    "43655",
    "43675",
    "43731",
    "43729",
    "43728",
    "43740",
    "43751",
    "43748",
    "43747",
    "43752",
    "43745",
    "43724",
    "43723",
    "43765",
    "43767",
    "43181",
    "43269",
    "43270",
    "43279",
    "43437",
    "43597",
    "43607",
    "43602",
    "43616",
    "43609",
    "43612",
    "43647",
    "43651",
    "43662",
    "43714",
    "43774",
    "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"
  ],
  "textContent": "Servo 0.1.0 represents Servo’s biggest month ever, with a record **530 commits** and our first ever release on crates.io! For security fixes, see § Security.\n\nWith this release Servo becomes more accessible, thanks to **tab navigation** (@mrobinson, @Loirooriol, #42952, #43019, #43058, #43246, #43267, #43067), **keyboard navigation** with Alt+Shift and the **accesskey** attribute (@mrobinson, #43031, #43144, #43434), and **keyboard scrolling** with Space and Shift+Space (@mrobinson, #43322).\n\nWe’ve shipped several new web platform features:\n\n  * **< input type=range>** (@BudiArb, @rayguo17, @mrobinson, #41562)\n  * **< script blocking=render>** (@TimvdLippe, #43150)\n  * **< svg width>** and **< svg height>** (@Loirooriol, #43583)\n  * **‘X-Frame-Options’** (@TimvdLippe, #43539, #43708)\n  * **‘Content-Security-Policy: frame-ancestors’** (@TimvdLippe, #43630)\n  * **‘::first-letter’** styling (@minghuaw, @xiaochengh, @Loirooriol, #43027)\n  * **‘::placeholder’** styling (@stevennovaryo, #43053)\n  * **‘::file-selector-button’** styling (@lukewarlow, @AlexVasiluta, #43498)\n  * **‘background-blend-mode’** (@mrobinson, #43666)\n  * **‘content’** on **‘::marker’** (@niyabits, @Loirooriol, #43515)\n  * **‘list-style-type: <string>’** (@Loirooriol, #43111)\n  * **‘attr(namespace|local)’** and **‘clamp(none)’** (@Loirooriol, #43045)\n  * <system-color> (@longvatrong111, @mrobinson, #42529, #43105, #43107)\n  * <step-position> values **‘jump-start’** , **‘jump-end’** , **‘jump-none’** , and **‘jump-both’** (@yezhizhen, #43061)\n\n\n\nPlus a bunch of new DOM APIs:\n\n  * **CommandEvent** (@lukewarlow, #43190)\n  * **moveBefore()** on **Node** (@lukewarlow, #41238)\n  * **relatedTarget** on **MouseEvent** and **PointerEvent** (@simonwuelker, #42989)\n  * **command** on **HTMLButtonElement** (@lukewarlow, #43190)\n  * **selectedOptions** on **HTMLSelectElement** (@jakubadamw, #43017)\n  * **url** on **LargestContentfulPaint** (@shubhamg13, #42901, #42949)\n  * **crypto.subtle.digest()** for **TurboSHAKE** (@kkoyung, #43551)\n  * **crypto.subtle.getPublicKey()** for **ECDH** , **ECDSA** , **Ed25519** , **RSASSA-PKCS1-v1_5** , **RSA-PSS** , **RSA-OAEP** , and **X25519** (@kkoyung, @Taym95, #43073, #43093, #43106, #43115)\n\n\n\n**servoshell** is now installed as `servoshell` or `servoshell.exe`, rather than `servo` or `servo.exe` (@jschwe, @mrobinson, #42958). `--userscripts` has been removed for now, but anyone who uses it is welcome to reinstate it as a wrapper around User­Content­Manager::add­_script (@jschwe, #43573). We’ve fixed a bug where link hover status lines are sometimes not legible (@simartin, #43320), and we’re working on getting servoshell signed for macOS to avoid getting blocked by Gatekeeper (@jschwe, #42912).\n\nAfter a long effort by @valpackett, @dlrobertson, and more recently @nortti0 and @sagudev (#43116, #43134), we can now build Servo for **FreeBSD**! Note that Servo 0.1.0 still has some issues that need to be worked around, but you can get all the details in #44601.\n\nA great deal of work went into making the **crates.io release** possible, including renaming `libservo` to just `servo` (@jschwe, #43141), making each package self-contained (@jschwe, #43180, #43165), fixing build issues (@delan, @jschwe, #43170, #43458, #43463) and crates.io compliance issues (@jschwe, #43459), configuring package metadata (@jschwe, @StaySafe020, #43078, #43264, #43451, #43457, #43654), and organising our dependency tree (@jschwe, @yezhizhen, @webbeef, @mrobinson, #42916, #43243, #43263, #43516, #43526, #43552, #43615, #43622, #43273, #43092). As a result, you can now take your first step towards embedding Servo in a Rust app with:\n\n\n    $ cargo add servo\n\nThis is another big update, so here’s an outline:\n\n  * Security\n\n  * Work in progress\n\n  * For developers\n\n  * Embedding and automation\n\n  * More on the web platform\n\n  * Performance and stability\n\n\n\n\n## Security   \n\n**crypto.subtle.deriveBits()** for **X25519** checking for all-zero secrets, and **verify()** for **HMAC** comparing signatures, are now done **in constant time** (@kkoyung, #43775, #43773).\n\n**‘Content-Security-Policy’** now handles redirects correctly (@TimvdLippe, #43438), and sends violation reports with the correct **blockedURI** and **referrer** (@TimvdLippe, #43367, #43645, #43483). The policy in <meta> now combines with the policy sent in HTTP headers, rather than overriding it (@TimvdLippe, @elomscansio, #43063). When checking nonces, we now reject elements with duplicate attributes (@dyegoaurelio, #43216).\n\nThe document containing an **< iframe>** can no longer access the contents of error pages (@TimvdLippe, #43539), and CSP violations inside an <iframe> are now correctly reported (@TimvdLippe, #43652).\n\n## Work in progress   \n\nWe’ve landed more work towards supporting **IndexedDB** , under `--pref dom­_indexeddb­_enabled` (@arihant2math, @gterzian, @Taym95, @jerensl, #42139, #42727, #43096, #43041, #42451, #43721, #43754, #42786), and towards supporting **IntersectionObserver** , under `--pref dom­_intersection­_observer­_enabled` (@stevennovaryo, @mrobinson, #42251).\n\nWe’re continuing to implement **document.execCommand()** for **rich text editing** (@TimvdLippe, #43177), under `--pref dom­_exec­_command­_enabled`. **‘beforeinput’** and **‘input’** events are now fired when executing supported and enabled commands (@TimvdLippe, #43087), the **‘defaultParagraphSeparator’** and **‘styleWithCSS’** commands are now supported (@TimvdLippe, #43028), and the **‘delete’** command is partially supported (@TimvdLippe, #43016, #43082).\n\nWe’re also working on the Font Loading API (@simonwuelker, #43286), under `--pref dom­_fontface­_enabled`. **new FontFace()** now accepts ArrayBuffer in its `source` argument (@simonwuelker, #43281).\n\nAll of the features above are enabled in servoshell’s experimental mode.\n\nWork on **accessibility** support for web contents continues under `--pref accessibility­_enabled`. There was a breaking change in the embedding API (@delan, @alice, #43029), and we’ve landed support for “grafting” the accessibility tree of a document into that of its containing webview (@delan, @alice, #43012, #43013, #43556). As a result, when you navigate, separate documents can have separate accessibility trees without complicating the embedder.\n\n**< link rel=modulepreload>** is now partially supported (@Gae24, #42964), though recursive fetching of descendants is gated by `--pref dom­_allow­_preloading­_module­_descendants` (@Gae24, #43353).\n\nFor a long time, Servo has had some support for the Web Bluetooth API under `--pref dom­_bluetooth­_enabled`. We’ve recently reworked our implementation to adopt btleplug, the cross-platform Rust-native Bluetooth LE library (@webbeef, #43529, #43581).\n\nWe’re now implementing the Web Animations API, starting with AnimationTimeline and DocumentTimeline (@mrobinson, #43711).\n\nWe’ve landed more fixes to Servo’s async parser (@simonwuelker, #42930, #42959), under `--pref dom­_servoparser­_async­_html­_tokenizer­_enabled`. If we can get the feature working more reliably (#37418), it could **halve the energy** Servo spends on parsing, **lower latency** for pages that don’t use document.write(), and even **improve the html5ever API** for the ecosystem.\n\n## For developers   \n\nServo’s DevTools feature now has partial support for inspecting **service workers** (@CynthiaOketch, #43659), as well as using the **navigation controls** along the top of the UI (@brentschroeter, @eerii, #43026).\n\nIn the **Inspector** tab, we’ve fixed a bug where the UI stops updating when navigating to a new page (@brentschroeter, #43153).\n\nIn the **Console** tab, you can now evaluate JavaScript in **web workers** and **service workers** (@SharanRP, #43361, #43492).\n\nIn the **Debugger** tab, you can now **Step In** , **Step Out** , and **Step Over** (@eerii, @atbrakhi, #42907, #43040, #43042, #43135). We’ve landed partial support for the **Scopes** panel (@eerii, @atbrakhi, #43166, #43167, #43232), the **Call stack** panel (@atbrakhi, @eerii, #43015, #43039), and showing you information when **hovering over objects** , **arrays** , **functions** , and other values (@atbrakhi, @eerii, #43319, #43356, #43456, #42996, #42936, #42994).\n\nWe’ve fixed some long-outstanding bugs where the **DevTools UI may stop responding** due to protocol desyncs (@brentschroeter, @eerii, #43230, #43236), or due to messages from multiple Servo threads being interleaved (@brentschroeter, @eerii, #43472).\n\nFor developers of Servo itself, mach can be a bit opaque at times. To make mach more transparent and composable, we’ve added `mach print-env` and `mach exec` commands (@jschwe, #42888).\n\nWe’re also working on a new dev container, which will provide an alternative to our usual procedures for setting up a Servo build environment (@jschwe, @sagudev, #43127, #43131, #43139).\n\n## Embedding and automation   \n\nBreaking changes:\n\n  * Servo::`set­_accessibility­_active()` is now WebView::set­_accessibility­_active() (@delan, @alice, #43029), to make the API harder to misuse (see the docs for more details).\n\n  * What was previously named WebView::`pinch­_zoom()` has been renamed to adjust­_pinch­_zoom(), and we’ve added a pinch­_zoom() method that lets you read the current pinch zoom level (@chrisduerr, #43228).\n\n  * WebView::`set­_delegate()`, `set­_clipboard­_delegate()`, and `set­_gamepad­_provider()` are now WebViewBuilder::delegate(), clipboard­_delegate(), and gamepad­_delegate() (@mrobinson, #43205, #43233). Note that set­_gamepad­_**provider**() is now gamepad­_**delegate**(), consistent with the `GamepadProvider` rename below.\n\n  * WebViewDelegate::show­_bluetooth­_device­_dialog() has been reworked to use the same “request object” pattern as the `request­_*()` methods, giving you a Bluetooth­Device­Selection­Request with clear methods (@webbeef, #43580).\n\n  * `GamepadProvider` has been renamed to GamepadDelegate, and `gamepad­_provider()` on WebView has been renamed to `gamepad­_delegate()` (@mrobinson, #43233).\n\n  * The empty default implementation of EventLoopWaker::wake has been removed, because it almost never makes sense for a new custom impl to leave the method empty (@chrisduerr, @mrobinson, #43250).\n\n  * Opts::`print­_pwm` is now DiagnosticsLogging::progressive­_web­_metrics (@mrobinson, #43209).\n\n\n\n\nRemoved from our API:\n\n  * Opts::`nonincremental­_layout` (@mrobinson, #43207) – no replacement. This only really worked in legacy layout.\n\n  * Opts::`user­_stylesheets` (@mrobinson, #43206) – use UserContentManager::add­_stylesheet() instead. This is how servoshell’s `--user-stylesheet` option works.\n\n\n\n\nYou can now read and write cookies with SiteDataManager::cookies­_for­_url() and set­_cookie­_for­_url() (@longvatrong111, #43600).\n\nClipboardDelegate and StringRequest are now exposed to the public API, allowing you to implement custom clipboard delegates (@jdm, @chrisduerr, #43203, #43261). You can pass your custom delegate to WebViewBuilder::clipboard­_delegate().\n\nYou can now get the EmbedderControlId associated with an InputMethodControl by calling InputMethodControl::id() (@chrisduerr, #43248).\n\nPixelFormat now implements Debug (@chrisduerr, @mrobinson, #43249).\n\nWe’ve improved the docs for Servo, ServoBuilder, WebViewBuilder, RenderingContext (@chrisduerr, #43229), EmbedderControlId, EmbedderControlRequest, EmbedderControlResponse, SimpleDialogRequest, AlertResponse, ConfirmResponse, PromptResponse, EmbedderMsg (@mukilan, #43564), ResourceReaderMethods (@jschwe, @mrobinson, #43769), servo::input­_events (@mukilan, #43681), and WheelDelta (@yezhizhen, @mrobinson, #43210).\n\nWe fixed a deadlock in **WebDriver** that occurs under heavy use of **actions** from multiple input sources (@yezhizhen, #43202, #43169, #43262, #43275, #43301), **‘pointerMove’ actions** with a ‘duration’ are now smoothly interpolated (@yezhizhen, #42946, #43076).\n\n**Add Cookie** is now more conformant (@yezhizhen, #43690), which led to Servo developers landing a spec patch. **‘pause’ actions** are now slightly more efficient (@yezhizhen, #43014), and we’ve fixed a bug where **‘wheel’ actions** fail to interleave with other actions (@yezhizhen, #43126).\n\n## More on the web platform   \n\n**Carets now blink** in text fields (@mrobinson, #43128). You can configure or disable blinking carets with `--pref editing_caret_blink_time=0` or a duration in milliseconds. **Clicking to move the caret** is more forgiving now (@mrobinson, #43238), and moving the caret by a **word at a time** is more conventional on Windows and Linux, with Ctrl instead of Alt (@mrobinson, #43436). We’ve also fixed a bug where pressing the arrow keys in text fields both moves the caret (good) and scrolls the page (bad), and fixed a bug where the caret fails to render on empty lines (@mrobinson, @freyacodes, #43247, #42218).\n\n**Input** has improved, with more responsive **touchpad scrolling** on Linux (@mrobinson, @chrisduerr, #43350). **Pointer events** and **mouse events** can now be **captured across shadow DOM boundaries** (@simonwuelker, #42987), and we’ve now started working towards shadow-DOM-compatible focus (@mrobinson, #43811). Pressing **Space** or **Enter** inside text fields no longer causes them to be clicked (@mrobinson, #43343).\n\nThe **lang** attribute is now taken into account when shaping, which is important for the correct rendering of Chinese and Japanese text (@RichardTjokroutomo, @mrobinson, #43447). **‘font-weight’** is now matched more accurately when no available font is an exact match (@shubhamg13, #43125).\n\n**Navigation** is one of the most complicated parts of HTML: navigating can run some JavaScript that replaces the page, just run some JavaScript, or depending on the response, do nothing at all. **< iframe>** makes navigation doubly complicated: the document containing an <iframe> can observe and interact with the document inside the <iframe> in various ways, often synchronously. This has been the source of many bugs over the years, but we’ve recently fixed one of those major issues (@jdm, #43496).\n\n`javascript:` URLs are a massive special case with many quirks, and <iframe> has its own big edge cases.\n\n**new Worker()** now supports **JS modules** (@pylbrecht, @Gae24, #40365), and **CanvasRenderingContext2D** now supports drawing text with **Variation Selectors** , allowing you to control things like emoji presentation and CJK shaping (@yezhizhen, #43449).\n\nServo now fires **‘pointerover’** , **‘pointerout’** , **‘pointerenter’** , and **‘pointerleave’** events on web content (@webbeef, #42736), **‘scroll’** events on **VisualViewport** (@stevennovaryo, #42771), and **‘scrollend’** events on **Document** , **Element** , and **VisualViewport** (@abdelrahman1234567, @mrobinson, #38773). We also fire **‘error’** events when **event handler** attributes contain syntax errors (@simonwuelker, #43178).\n\nWe’ve improved the default appearance of **< summary>** (@Loirooriol, #43111), **< select>** (@lukewarlow, #43175), **< input type=file>** (@lukewarlow, @AlexVasiluta, @lukewarlow, #43498, #43186), and **< textarea>** and **< input type=text>** and friends (@mrobinson, #43132), plus **‘::marker’** in mixed LTR/RTL content (@Loirooriol, #43201). **< select>** also now requires user interaction to open the picker (@SharanRP, #43485).\n\n**< form action>**, **< iframe src>**, **open(url)** on **XMLHttpRequest** , **new EventSource(url)** , and **new Worker(url)** now correctly resolve the URL with the page encoding (@SharanRP, @jdm, @jayant911, @Veercodeprog, @sabbCodes, #43521, #43554, #43572, #43537, #43634, #43588).\n\n**‘direction’** now works on grid containers (@nicoburns, #42118), **SVG images** can now be used in **‘border-image’** (@shubhamg13, #42566), **‘linear-gradient()’** now dithers to reduce banding (@Messi002, #43603), **‘letter-spacing’** no longer applies to invisible zero-width formatting characters (@simonwuelker, #42961), and **‘:active’** now matches disabled or non-focusable elements too, as long as they are being clicked (@webbeef, #42935).\n\n**DOMContentLoaded** timings in **Performance­Navigation­Timing** are more accurate (@simonwuelker, #43151). **Performance­Paint­Timing** and **Largest­Contentful­Paint** are more accurate too, taking <iframe> into account (@shubhamg13, #42149), and checking for and ignoring things like broken images and transparent backgrounds (@shubhamg13, #42833, #42975, #43475).\n\nWe’ve improved the conformance of **JS modules** (@Gae24, #43585), **< button command>** (@lukewarlow, #42883), **< font size>** (@shubhamg13, #43103), **< link media>** and **< link type>** (@TimvdLippe, #43043), **< option selected>** (@SharanRP, #43582), **< script integrity>** and **< style integrity>** (@Gae24, #42931), **EventSource** (@mishop-15, #42179), **SubtleCrypto** (@kkoyung, #42984, #43315, #43533, #43519), **Worker** (@simonwuelker, #43329), **HTMLVideoElement** (@shubhamg13, #43341), **dataset** on **Element** (@TimvdLippe, #43046), and **querySelector()** and **querySelectorAll()** (@simonwuelker, #42991).\n\nWe’ve fixed bugs related to **error reporting** (@simonwuelker, @xZaisk, @yezhizhen, @eyupcanakman, #43191, #43323, #43101, #43560), **event loops** (@jayant911, #43523), **focus** (@jakubadamw, #43431), **quirks mode** (@mrobinson, @Loirooriol, @lukewarlow, #42960, #43368), **< iframe>** (@TimvdLippe, @jdm, #43539, #43732), the **‘animationstart’** and **‘animationend’** events (@simonwuelker, #43454), the **‘touchmove’** event (@yezhizhen, #42926), **CanvasRenderingContext2D** (@simonwuelker, #43218), **Worker** (@bruno-j-nicoletti, #43213), **‘:active’** on <input> (@mrobinson, #43722), **‘overflow: scroll’** on ‘::before’ and ‘::after’ (@stevennovaryo, #43231), **‘position: absolute’** (@yoursanonymous, @Loirooriol, #43084), and **< img>** and **< svg>** without width or height attributes (@Loirooriol, #42666). Fixing that last bug led to Servo developers finding two spec issues!\n\nWe’ve landed partial support for using **CSS counters** in ‘list-style-type’ on ‘display: list-item’ and ‘content’ on ‘::marker’, but the counter values themselves are not calculated yet, so all list items still read as `0.` or similar. In any case, you can use a <counter-style-name> or ‘symbols()’ in ‘list-style-type’, and ‘counter()’ and ‘counters()’ in ‘content’ (@Loirooriol, #43111).\n\nWe’ve also landed partial support for **< marquee>** and the **HTMLMarqueeElement** interface, including basic layout, but the contents are not animated yet (@mrobinson, @lukewarlow, #43520, #43610).\n\nServo now exposes several attributes that have no direct effect, but are needed for web compatibility (@lukewarlow, #43500, #43499, #43502, #43518):\n\n  * **noHref** on **HTMLAreaElement**\n  * **hreflang** , **type** , **charset** on **HTMLAnchorElement**\n  * **useMap** on **HTMLInputElement** and **HTMLObjectElement**\n  * **longDesc** on **HTMLIFrameElement** and **HTMLFrameElement**\n\n\n\n## Performance and stability   \n\nWe’ve fixed **sluggish scrolling** on long documents like this page on docs.rs (@webbeef, @yezhizhen, #43074, #43138), and reduced the **memory usage of BoxFragment** by **10%** (@stevennovaryo, #43056). **about:memory** now has a **Force GC** button (@webbeef, #42798), and no longer reports all processes as content processes in multiprocess mode (@webbeef, #42923).\n\n**Web fonts** are no longer fetched more than once, and they no longer cause reflow when they fail to load (@minghuaw, #43382, #43595). We’re also working towards better caching for shaping results (@mrobinson, @lukewarlow, @Loirooriol, #43653). **Event handler** attribute lookup is more efficient now (@Narfinger, #43337), and we’ve made **DOM tree walking** more efficient in many cases (@Narfinger, #42781, #42978, #43476).\n\n**crypto.subtle.encrypt()** , **decrypt()** , **sign()** , **verify()** , **digest()** , **importKey()** , **unwrapKey()** , **decapsulateKey()** , and **decapsulateBits()** are more efficient now (@kkoyung, #42927), thanks to a recent spec update.\n\nMore of Servo now **uses cheaper crossbeam channels** instead of IPC channels, unless Servo is running in multiprocess mode, or **avoids IPC altogether** (@Narfinger, @jschwe, @Taym95, #42077, #43309, #42966). We’ve also reduced clones, allocations, conversions, comparisons, and borrow checks in many parts of Servo (@simonwuelker, @kkoyung, @mrobinson, @Narfinger, @yezhizhen, @TG199, #43212, #43055, #43066, #43304, #43452, #43717, #43780, #43088, #43226).\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, #42937, #42982, #43018, #43071, #43222, #43288, #43544, #43563, #43631).\n\nWe’ve fixed a crash caused by an IPC resource leak when making **many requests over time** (@yezhizhen, #43381), and some bugs found by **ThreadSanitizer** and **--debug-mozjs** (@jdm, @Loirooriol, #42976, #42963, #43487). We’ve also fixed crashes in **CanvasRenderingContext2D** (@yezhizhen, #43449), **Crypto** (@rogerkorantenng, #43501), **devtools** (@simonwuelker, #43133), **event handler** attributes (@simonwuelker, #43178), **Promise** (@Narfinger, @jdm, #43470), and **WebDriver** (@Tarmil, @yezhizhen, #42739, #43381).\n\nWe’ve continued our long-running effort to **use the Rust type system** to make certain kinds of dynamic borrow failures impossible (@Narfinger, @Gae24, @Uiniel, @TimvdLippe, @yezhizhen, @sagudev, @PuercoPop, @pylbrecht, @arabson99, @jayant911, #42957, #43108, #43130, #43215, #43183, #43219, #43245, #43220, #43252, #43268, #43184, #43277, #43278, #43284, #43302, #43312, #43348, #43327, #43362, #43365, #43383, #43432, #43259, #43439, #43473, #43481, #43480, #43479, #43525, #43535, #43543, #43549, #43570, #43571, #43569, #43579, #43584, #43657, #43713).\n\nThanks to a wide range of people, many of whom were contributing to Servo for their first time, we’ve also landed a bunch of architectural improvements (@elomscansio, @mukilan, #43646), cleanups (@simartin, @SharanRP, @TG199, @sabbCodes, @niyabits, @eerii, @atbrakhi, #43276, #43285, #43532, #43778, #43771, #43566, #43567, #43587, #43140, #43316), and refactors (@sabbCodes, @arabson99, @jayant911, @StaySafe020, @saydmateen, @eerii, @TimvdLippe, @elomscansio, @CynthiaOketch, #43614, #43641, #43619, #43642, #43623, #43656, #43644, #43672, #43664, #43676, #43684, #43679, #43678, #43655, #43675, #43731, #43729, #43728, #43740, #43751, #43748, #43747, #43752, #43745, #43724, #43723, #43765, #43767, #43181, #43269, #43270, #43279, #43437, #43597, #43607, #43602, #43616, #43609, #43612, #43647, #43651, #43662, #43714, #43774).\n\n## Donations   \n\nThanks again for your generous support! We are now receiving **7167 USD/month** (+2.6% from February) 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 **37 GitHub users** (+5 from February) 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**7167** 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": "March in Servo: keyboard navigation, better debugging, FreeBSD support, and more!",
  "updatedAt": "2026-04-30T00:00:00.000Z"
}