February in Servo: faster layout, pause and resume scripts, and more!
Servo 0.0.6 includes some exciting new features:
- < button command> and < button commandfor> (@lukewarlow, #41237)
- ‘:modal’ selectors on < dialog> (@lukewarlow, #42201)
- ‘@property’ rules (@yezhizhen, @Loirooriol, #42136, #42858)
- ‘alignment-baseline’ and ‘baseline-shift’ (@Loirooriol, #42361)
- ‘Content-Security-Policy: base-uri’ (@WaterWhisperer, #42272)
- partial support for < iframe loading=lazy> (@TimvdLippe, #41959)
- partial support for ‘transform-style: preserve-3d’ (@simonwuelker, #42755)
Plus a bunch of new DOM APIs:
- most of the Pointer Events API (@webbeef, #41290)
- the UserActivation API (@stevennovaryo, #42060)
- import.meta.resolve() (@Gae24, #42506)
- integrity in < script type=importmap> (@Gae24, #42604)
- the formData() method on Request (@Taym95, #42041)
- the alpha property on HTMLInputElement (@simonwuelker, #42293)
- tabIndex on HTMLElement and SVGElement (@mrobinson, @Loirooriol, #42913)
- fullscreenElement on Document and ShadowRoot (@onsah, #42401)
- toJSON() on PerformancePaintTiming (@shubhamg13, #42396)
- navigator.pdfViewerEnabled (@simonwuelker, #42277)
- keyPath on IDBIndex (@arihant2math, #42431)
- createIndex() , deleteIndex() , and index() on IDBObjectStore (@arihant2math, @bulltickr, #38840, #42440, #42443)
This is a big update, so here’s an outline:
Work in progress – accessibility, execCommand()
Developer tools – localhost only by default, Inspector, Console, Debugger
servoshell – servo:config, F5 to reload
Embedding API – offline builds, user stylesheets, context menus, gamepad API
More on the web platform – font fallback, cookies, IndexedDB, First and Largest Contentful Paint
Performance and stability – about:memory, incremental layout, shared memory
Bug fixes – Windows arm64, layout, DOM events, shadow DOM
Donations – how you can help Servo flourish
Work in progress
We’ve started working on accessibility support for web content (@alice, @delan, #42333, #42402), gated by a pref (--pref accessibility_enabled). Each webview will be able to expose its own accessibility tree, which the embedder can then integrate into its own accessibility tree. As part of this work:
AccessKit now supports combining accessibility trees with its new “subtree” feature (@DataTriny, @delan, @lukewarlow, @alice, AccessKit/accesskit#655, AccessKit/accesskit#641)
egui has been migrated to the new AccessKit API (@delan, @lukewarlow, @lucasmerlin, @DataTriny, emilk/egui#7850)
we added a Servo API for activating accessibility features (@delan, @alice, #42336), although this has since become a WebView API
We’ve started implementing document.execCommand() (@TimvdLippe, #42621, #42626, #42750), gated by a pref (--pref dom_exec_command_enabled). This feature is also enabled in experimental mode , and together with contenteditable , it’s critical for rich text editing on the web. The work done in February includes:
- document.queryCommandEnabled() (@TimvdLippe, #42634)
- document.queryCommandSupported() (@TimvdLippe, #42731)
- document.queryCommandIndeterm() , queryCommandState() , and queryCommandValue() (@TimvdLippe, #42748)
- the canonicalize whitespace algorithm – this is used by the ‘delete’, ‘forwardDelete’, and ‘insertText’ commands (@TimvdLippe, #42704)
- contentEditable on HTMLElement – for execCommand() only, excluding any support for interactive editing (@TimvdLippe, #42633, #42734)
Developer tools
DevTools has seen some big improvements in February!
When enabled in servoshell, the DevTools server is more secure by default, listening only on localhost when only a port number is specified (@Narfinger, #42502). You can open the port for remote debugging by passing a full SocketAddr, such as --devtools=[::]:6080 or --devtools=0.0.0.0:6080.
In the Inspector tab, you can now edit DOM attributes , and the DOM tree updates when attributes change (@simonwuelker, #42601, #42785). You can now list the event type and phase of event listeners attached to a DOM node as well (@simonwuelker, #42355).
In the Console tab, objects can now be previewed when passed to console.log() and friends (@simonwuelker, #42296, #42510, #42752), and boolean values are now syntax highlighted (@pralkarz, #42513).
In the Debugger tab, you can now pause and resume script execution, both manually and when breakpoints are hit (@eerii, @atbrakhi, #42599, #42580, #42874). We’ve also started working on other debugger features (@atbrakhi, @eerii, #42306), including stepping execution (@eerii, @atbrakhi, #42844, #42878, #42906), so once again stay tuned!
Servo 0.0.6 showing DevTools debugger setting breakpoints, pausing on those breakpoints, and resuming script execution
servoshell
Back in August, we added a servo:preferences page to servoshell that allows you to set some of Servo’s most common preferences at runtime (@jdm, #38159).
servoshell now has a servo:config page (@arihant2math, #40324), allowing you to set any preference, even internal ones. Note that preference changes are not yet persistent, and not all prefs take effect when changed at runtime.
You can now press F5 to reload the page in servoshell (@Narfinger, #42538), in addition to pressing Ctrl+R or ⌘R.
We’ve fixed a regression where the caret stopped being visible in the location bar (@mrobinson, #42470).
Embedding API
Servo is now easier to build offline , using the complete source tarball included in each release (@jschwe, #42852). Go to a release on GitHub, then download servo-[version]-src-vendored.tar.gz to get started.
You can now add and remove user stylesheets with UserContentManager::add_stylesheet and remove_stylesheet, and remove user scripts with UserContentManager::remove_script (@mukilan, #42288). Previously user stylesheets were only configurable via servoshell’s --user-stylesheet option.
User stylesheets work a bit differently to userstyles , since they cascade via the user origin, not the author origin. For more details about the tradeoffs, check out Customising the web: browsers as user agents (slides).
Before opening any context menus on behalf of web content, Servo now closes any context menus that were opened by web content (@mrobinson, #42487), to avoid UI problems on some platforms. This is done by calling WebViewDelegate::hide_embedder_control before calling show_embedder_control in those cases.
Input method events from web content now indicate whether or not the virtual keyboard should be shown (@stevennovaryo, @mrobinson, #42467), with the new InputMethodControl::allow_virtual_keyboard method. Generally the virtual keyboard should only be shown when the page has sticky activation.
We’re reworking our gamepad API , with WebViewDelegate::play_gamepad_haptic_effect and stop_gamepad_haptic_effect being replaced by a new API that (as of the end of February at least) is known as GamepadProvider (@atbrakhi, #41568). The old methods are no longer called (#43743), and may be removed at some point.
We now have better diagnostic output when we fail to create an OpenGL context (@mrobinson, #42873), including when the OpenGL versions supported by the device are too old.
Servo::constellation_sender was removed (@jdm, #42389), since it was never useful to embedders.
We’ve also made some changes to Preferences:
devtools_server_portis now devtools_server_listen_address, and can now take either a port number (as before) or a full SocketAddr (@Narfinger, #42502)dom_worklet_blockingsleepis nowdom_worklet_blockingsleep_enabled(@mukilan, #42897)Removed many unused preferences (@mukilan, #42897) –
js_asyncstack,js_discard_system_source,js_dump_stack_on_debuggee_would_run,js_ion_offthread_compilation_enabled,js_mem_gc_allocation_threshold_avoid_interrupt_factor,js_mem_gc_allocation_threshold_factor,js_mem_gc_allocation_threshold_mb,js_mem_gc_decommit_threshold_mb,js_mem_gc_dynamic_heap_growth_enabled,js_mem_gc_dynamic_mark_slice_enabled,js_shared_memory,js_throw_on_asmjs_validation_failure,js_throw_on_debuggee_would_run,js_werror_enabled, andnetwork_mime_sniff
More on the web platform
If you navigate to a video file or audio file as a document , the player now has controls (@webbeef, #42488).
Images now rotate according to their EXIF metadata by default (@rayguo17, #42567), like they would once we add support for ‘image-orientation: from-image’.
We’re implementing system-font-aware font fallback (@mrobinson, #42466), with support for this on macOS landing this month (@mrobinson, #42776). This allows Servo to render text in scripts that are not covered by web fonts or any of the fonts on Servo’s built-in lists of fallback fonts, as long as they are covered by fonts installed on the system.
Servo now supports the newer pointermove , pointerdown , pointerup , and pointercancel events (@webbeef, #41290). The older touchmove , touchstart , touchend , and touchcancel events continue to be supported.
The default language in ‘Accept-Language’ and navigator.language is now taken from the $LANG environment variable if present (@webbeef, #41919), rather than always being set to en-US.
< input type=color> now supports any CSS color value (@simonwuelker, #42275), including the more complex values like color-mix(). We’ve also landed the colorspace attribute (@simonwuelker, #42279), but only in the web-facing side of Servo for now, not the embedding API or in servoshell.
‘vertical-align’ is now a shorthand for ‘alignment-baseline’ and ‘baseline-shift’ (@Loirooriol, #42361), and scrollParent on HTMLElement is now a function per this recent spec update (@TimurBora, #42689).
Cookies are now more conformant (@sebsebmc, #42418, #42427, #42435). ‘Expires’ and ‘Max-Age’ attributes are now handled correctly in ‘Set-Cookie’ headers, get() and getAll() on CookieStore now trim whitespace in cookie names and values, and the behaviour of set() on CookieStore has been improved.
< iframe> elements are now more conformant in how load events are fired on the element and its contentWindow (@TimvdLippe, #42254), although there are still some bugs. This has long behaved incorrectly in Servo, and it has historically caused many problems in the Web Platform Tests.
IndexedDB is now more conformant in our handling of transactions (@Taym95, #41508, #42732), and when opening and closing connections (@gterzian, @Taym95, #42082, #42669).
We’ve started implementing Largest Contentful Paint timings (@shubhamg13, #42024), and we’ve landed a bunch of improvements to how First Contentful Paint timings work in Servo:
- we now include ‘background-image’ (@shubhamg13, #42569)
- we now include ‘border-image’ (@shubhamg13, #42581)
- we now ignore subtrees with ‘opacity: 0’ (@shubhamg13, #42768)
- we now ignore zero-sized subtrees (@shubhamg13, #42178)
- we now ignore (@shubhamg13, #42498)
- we now ignore and unless they actually have an image (@shubhamg13, #42411)
- we now ignore mouse moves when deciding when to stop measuring (@shubhamg13, #41999)
new WebSocket() now resolves relative URLs (@webbeef, #42425).
requestFullscreen() on Element now requires user activation (@stevennovaryo, #42060).
performance.getEntries() now returns PerformanceResourceTiming entries for navigations in (@muse254, #42270).
When geolocation is enabled (--pref dom_geolocation_enabled), navigator.geolocation.getCurrentPosition() and watchPosition() now support the optional errors argument (@arihant2math, #42295).
We now support the ‘-webkit-text-security’ property in CSS (@mrobinson, #42181), which is not specified anywhere but required for MotionMark.
Performance and stability
Our about:memory page now knows how to report many new kinds of memory usage , including the DevTools server (@Narfinger, #42478, #42480), WebGL (@sagudev, #42570), localStorage and sessionStorage (@arihant2math, #42484), and some of the memory used by IndexedDB (@arihant2math, #42486). We’ve also started internally tracking the memory usage of the media subsystem (@Narfinger, #42504) and WebXR (@Narfinger, #42505).
Layout has seen a lot of performance work in February, with our main focus being on improving incremental layout of the box tree and fragment tree.
We now have our first truly incremental box tree layout (@mrobinson, @Loirooriol, @lukewarlow, #42700), rather than our previous “dirty roots”-based approach. Depending on how they were damaged, some boxes for floats (as above, #42816), independent formatting contexts (as above, #42783), and their descendants (as above, #42582) can now be reused, and they avoid damaging their parents (as above, #42847). We also destroy boxes with ‘display: none’ earlier in the layout process (as above, #42584).
Incremental fragment tree layout is improving too! Whereas we previously had to decide whether to run fragment tree layout in an “all or nothing” way, we can now reuse cached fragments in independent formatting contexts (@mrobinson, @Loirooriol, @lukewarlow, #42687, #42717, #42871). We can also measure how much work is being done on each layout (as above, #42817).
Servo uses shared memory for many situations where copying data over channels would be too expensive, such as for images and fonts. In multiprocess mode (--multiprocess), we use the operating system to create the shared memory in a way that can be shared with other processes, such as shm_open(3) or CreateFileMappingW, but this consumes resources that can sometimes be exhausted. We only need to use those kinds of shared memory in multiprocess mode, so we’ve reworked Servo to use Arc<Vec<u8>> in single-process mode (@Narfinger, #42083), which should avoid resource exhaustion.
Parsing web pages is complicated: we want pages to render incrementally as they stream in from the network, and we want to prefetch resources, but scripts can call document.write(), which injects markup “on the spot”. This is further complicated if that markup also contains a
Discussion in the ATmosphere