My penguin avatar

This Week in Ladybird #4

Published on 2023-04-16.

Overview of changes across the Ladybird Browser project in the week from April 10 to April 16 (plus everything merged Sunday evening) :^)


In chronological order:

Browser: Have BookmarksBarWidget signal bookmark changes for Tab

#18096 by @kemzeb

This ensures that the bookmark button is updated correctly when a bookmark for the currently active tab is changed:

#18172 by @krkk

This adds support for resolving the following CSS properties so that Window.getComputedStyle() can return their actual values:

LibWeb: Return from "the end" during HTML fragment parsing

#18224 by @Lubrsi

This adds an early return to the HTML parser's the end step when parsing HTML fragments, fixing some issues caused by the spec not matching web reality (Luke filed whatwg/html#8646 for that back in December).

It also features the longest commit message you will ever see for a two line change!

LibVideo+LibWeb: Generalize PlaybackManager for use within LibWeb...and use it

#18264 by @trflynn89

This updates the video element implementation in LibWeb to use the PlaybackManager class from LibVideo, which abstracts away the exact demuxer being used, provides buffering, and a few other things.

This is already being used in SerenityOS's VideoPlayer application, so future improvements once again benefit multiple parts of the system!

LibWeb: Implement a few methods on WritableStream and WritableStreamDefaultWriter

#18265 by @mattco98

More work on the Streams API, at this rate it might be feature-complete by the end of the month!

This implements the following APIs:

LibWeb: Implement WritableStreamDefaultWriter.write() and an AO involved in WritableStream's constructor

#18266 by @mattco98

This implements the WritableStreamDefaultWriter.write() API and various related AOs.

LibWeb: Convert video control dimensions from CSSPixels to DevicePixels

#18270 by @trflynn89

The video controls were initially developed on a HiDPI machine, and would thus look too large at 1x scaling. They now are sized in display-independent CSS pixels and converted to device pixels during painting.

LibWeb+AK: Get Google Street View working, along with SVG viewboxes, transforms, scaling, and hit testing!

#18271 by @MacDue

This PR implements all sorts of things with the goal of getting Google street View actually working, including looking and moving around!

And of course these features work in isolation too:

LibWeb: Track playback position and display a timeline on the layout node

#18281 by @trflynn89

We now keep track of the video's playback position and render a timeline accordingly. Seeking is not yet implemented, but this is of course a necessary prerequisite :^)

LibWeb: Begin adding ReadableByteStream interfaces

#18283 by @mattco98

This implements the following APIs:

As it turns out, BYOB stands for bring your own buffer and I'm somewhat surprised they named a Web API like that :^)

Nonetheless, very exciting to see some progress on the more efficient byte streams, too!

LibJS: Update spec numbers for the Intl NumberFormat v3 proposal

#18286 by @trflynn89

Much like this similar change from last week, the Intl NumberFormat v3 proposal has been merged into the main ECMA-402 spec, and we had to incorporate some final spec changes.

LibWeb: Implement URL.canParse(url, base)

#18287 by @networkException

This implements the brand new (last month) URL.canParse() API:

LibWeb: Convert calc() to spec's internal representation, fixing nested calc() in the process

#18289 by @AtkinsSJ

This re-implements calculated CSS values according to the CSS-VALUES-4 spec, fixing nested calc() in the process and allowing us to implement other functionality from that spec more easily later on.

For example, this is the internal representation of calc(100px + 30% - (120px / (2*4 + 3 ))):

LibWeb: Handle null values when making args for attributeChangedCallback

#18293 by @Lubrsi

This fixes incorrect handling of the DeprecatedString null state, which also returns true for is_empty() checks and would therefore create an empty JS string where a null value was expected.

This makes a lot of custom elements on the YouTube video page appear!

LibWeb: Create a video document for video/ MIME types on navigation

#18295 by @Lubrsi

We already create a basic DOM for images directly loaded via the URL bar so they can be shown in the web view, and now do the same for videos:

(video playback performance has improved a bit since then!)

LibWeb: Integrate ReadableByteStreamController into ReadableStreamController type

#18297 by @mattco98

More work on the Streams API. As a reviewer I'm very happy that Matthew is doing this incrementally :^)

LibJS: Comment all the things

#18336 by @linusg

I dusted off an old branch with the aim of adding spec comments to everything in LibJS/Runtime/ — we're not quite there yet, but it's a gradual process that often leads to small cleanups along the way :^)

LibJS: Make intrinsics getters and well-known symbol getters return NonnullGCPtr

#18343 by @linusg

Another ongoing effort in LibJS is updating raw pointers to either GCPtr or NonnullGCPtr — two lightweight wrappers around pointers to memory allocated on the JS heap and thus controlled by the garbage collector (GC).

In this case I updated all the well-known intrinsic objects (built-in constructors and prototypes mostly, written as %name% in the spec) and well-known symbols (@@name) to return NonnullGCPtrs instead of raw pointers:

- ArrayConstructor* Intrinsics::array_constructor();
+ NonnullGCPtr<ArrayConstructor> Intrinsics::array_constructor();

Even though many of the intrinsics are lazily allocated, calling their accessors is what causes that so a null pointer is never returned.

LibWeb: Whine instead of dying on unexpected box during line layout

#18344 by @awesomekling

This works around a VERIFY() (assertion) in the Inline Formatting Context that was slightly too optimistic and would cause crashes on various websites, including GitHub.

It's really annoying to have the entire web page crash because of some random unimplemented code path, so we largely avoid crashing macros like TODO() and VERIFY() in favour of no-op code paths that log a FIXME.

LibJS: Port more AOs to {Nonnull,}GCPtr

#18346 by @linusg

Doing the same as above to the return types of more AOs.

LibWeb: Don't match the root node of HTMLCollection

#18349 by @Lubrsi

When a HTMLCollection is created, e.g. via Element.getElementsByTagName(), it traverses the subtree from that element, which we have two slightly different methods for:

It now correctly uses the latter to not include the element the method was called on.

LibWeb+Ladybird: Add support for more CSS cursors in Ladybird

#18359 by @srikavin

This adds support for cursor: not-allowed; in LibWeb, and maps more cursors from the LibGfx StandardCursor enum to their Qt equivalents in Ladybird (previously, only the hand, i-beam, and arrow cursors were mapped).

LibWeb: Set Comment's prototype

#18362 by @Lubrsi

Quite possibly the best bug silliness to fix effectiveness ratio we've had so far. Simply by setting the correct prototype of any instantiated Comment object, thumbnails started appearing on YouTube!

Luke wrote a summary of their investigation of this bug, check out the PR if you're curious :^)

LibWeb: Honor column-gap and row-gap CSS properties in flex layout

#18363 by @awesomekling

Another case of web reality not matching the specs; the PR description explains this change nicely:

This isn't actually part of CSS-FLEXBOX-1, but all major engines honor these properties in flex layout, and it's widely used on the web.

There's a bug open against the flexbox spec where fantasai says the algorithm will be updated in CSS-FLEXBOX-2: w3c/csswg-drafts#2336

I've added comments to all the places where we adjust calculations for gaps with "CSS-FLEXBOX-2" so we can find them easily. When that spec becomes available, we can add proper spec links.

LibWeb: Do not dereference empty Optional in ReadableStream::visit_edges

#18367 by @trflynn89

A bug fix for ReadableStream, which would dereference an empty Optional<T> (which causes a crash) during garbage collection if its controller hasn't been set yet.

LibWeb/Streams: Couple of small cleanups

#18370 by @linusg

Have you noticed I'm in a spring cleaning mood yet? :^)

LibJS: Comment all the things (continued)

#18374 by @linusg

More of that. I think all the built-in objects are covered now…

LibWeb: Introduce DocumentState and update SessionHistoryEntry

#18378 by @kalenikaliaksandr

Alexander has adopted and continued Andreas' refactor from browsing contexts to navigables so we can start merging those changes, this is the beginning of that :^)

Ladybird+LibWebView: Add -P/--enable-callgrind-profiling option

#18383 by @MacDue

This adds an option to Ladybird to run WebContent processes in valgrind with callgrind enabled, which is useful for profiling on Linux! 🐧

LibWeb: Scale SVG stroke-width based on viewbox

#18388 by @MacDue

This fixes the clipping of strokes in quite a few cases and now fixes the Gartic Phone logo :^)

LibWeb: Honor gap between flex lines when using align-content: stretch

#18400 by @awesomekling

As usual, layout changes are best explained by the author themselves :^)

We have to take the cross gap into account when calculating the "sum of flex line cross sizes" in "Handle 'align-content: stretch'".

LibWeb: Fix multi-line flex column layouts with auto height on container

#18403 by @awesomekling

When sizing a flex container with flex-direction:column under a max-content height constraint, we were incorrectly truncating the infinite available height to 0 when collecting flex items into lines.

This caused us to put every flex item in its own flex line, which is the complete opposite of what we want during max-content intrinsic sizing, as the layout would grow wide but not tall.


During his CSS calc() refactor, Sam had a happy little accident. Luke's been trying all sorts of things on YouTube that work now (after briefly breaking the thumbnails layout), which is really impressive! And of course, there's always that one website complaining about your ad blocker… we happen to have one. And something's wrong with our rendering of the mozilla logo :^)

And that's all for this week! Lots of nice progress, video playback is improving every day, Street View basically works (pending some perf improvements), and I'd not be surprised if Luke makes even more of YouTube work next week.

Looks like it's possible to build a browser after all :^)

Loading posts...