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) :^)
Summary
In chronological order:
- Browser: Have
BookmarksBarWidget
signal bookmark changes forTab
- LibWeb: Resolve more background-related properties
- LibWeb: Return from "the end" during HTML fragment parsing
- LibVideo+LibWeb: Generalize PlaybackManager for use within LibWeb...and use it
- LibWeb: Implement a few methods on WritableStream and WritableStreamDefaultWriter
- LibWeb: Implement WritableStreamDefaultWriter.write() and an AO involved in WritableStream's constructor
- LibWeb: Convert video control dimensions from CSSPixels to DevicePixels
- LibWeb+AK: Get Google Street View working, along with SVG viewboxes, transforms, scaling, and hit testing!
- LibWeb: Track playback position and display a timeline on the layout node
- LibWeb: Begin adding ReadableByteStream interfaces
- LibJS: Update spec numbers for the Intl NumberFormat v3 proposal
- LibWeb: Implement URL.canParse(url, base)
- LibWeb: Convert
calc()
to spec's internal representation, fixing nestedcalc()
in the process - LibWeb: Handle null values when making args for attributeChangedCallback
- LibWeb: Create a video document for
video/
MIME types on navigation - LibWeb: Integrate ReadableByteStreamController into ReadableStreamController type
- LibJS: Comment all the things
- LibJS: Make intrinsics getters and well-known symbol getters return NonnullGCPtr
- LibWeb: Whine instead of dying on unexpected box during line layout
- LibJS: Port more AOs to {Nonnull,}GCPtr
- LibWeb: Don't match the root node of HTMLCollection
- LibWeb+Ladybird: Add support for more CSS cursors in Ladybird
- LibWeb: Set Comment's prototype
- LibWeb: Honor column-gap and row-gap CSS properties in flex layout
- LibWeb: Do not dereference empty Optional in ReadableStream::visit_edges
- LibWeb/Streams: Couple of small cleanups
- LibJS: Comment all the things (continued)
- LibWeb: Introduce DocumentState and update SessionHistoryEntry
- Ladybird+LibWebView: Add -P/--enable-callgrind-profiling option
- LibWeb: Scale SVG stroke-width based on viewbox
- LibWeb: Honor gap between flex lines when using align-content: stretch
- LibWeb: Fix multi-line flex column layouts with auto height on container
Browser: Have BookmarksBarWidget
signal bookmark changes for Tab
This ensures that the bookmark button is updated correctly when a bookmark for the currently active tab is changed:
LibWeb: Resolve more background-related properties
This adds support for resolving the following CSS properties so that Window.getComputedStyle()
can return their actual values:
background-attachment
background-clip
background-image
background-origin
background-position
background-repeat
background-size
LibWeb: Return from "the end" during HTML fragment parsing
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
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:
WritableStream
:WritableStreamDefaultWriter
:
LibWeb: Implement WritableStreamDefaultWriter.write() and an AO involved in WritableStream's constructor
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!
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
This implements the following APIs:
ReadableByteStreamController
:ReadableStreamBYOBRequest
:
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)
This implements the brand new (last month) URL.canParse()
API:
LibWeb: Convert calc()
to spec's internal representation, fixing nested calc()
in the process
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
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
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
More work on the Streams API. As a reviewer I'm very happy that Matthew is doing this incrementally :^)
LibJS: Comment all the things
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
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 NonnullGCPtr
s 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
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
Doing the same as above to the return types of more AOs.
LibWeb: Don't match the root node of HTMLCollection
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:
for_each_in_inclusive_subtree_of_type()
for_each_in_subtree_of_type()
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
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
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
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
Have you noticed I'm in a spring cleaning mood yet? :^)
LibJS: Comment all the things (continued)
More of that. I think all the built-in objects are covered now…
LibWeb: Introduce DocumentState and update SessionHistoryEntry
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
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
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
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
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.
Screenshots
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 :^)