I had made a stab at implementing this to determine whether it could
assist in fixing an issue where scroll_to_the_fragment was not getting
called at the appropriate time. It did not fix that issue, and actually
ended up breaking one of our in tree tests. In the meantime, factor out
this method into a standalone function.
These don't have to worry about the input not being valid UTF-8 and
so can be infallible (and can even return self if no changes needed.)
We use this instead of Infra::to_ascii_{upper,lower}_case in LibWeb.
There was no need to use FlyString for error messages, and it just
caused a bunch of churn since these strings typically only existed
during the lifetime of the error.
This way we don't have to allocate separate vector with both scroll and
sticky frame that is used for display list player (scroll and sticky
frames share id pool), so player could access offset by frame id.
No behavior change.
While Origin is defined in the HTML spec - this leaves us with quite an
awkward relationship as the URL spec makes use of AO's from what is
defined in the HTML spec.
To simplify this factoring, relocate Origin into LibURL.
Implements https://github.com/whatwg/html/pull/10007 which basically
moves style, layout and painting from HTML processing task into HTML
task with "rendering" source.
The biggest difference is that now we no longer schedule HTML event loop
processing whenever we might need a repaint, but instead queue a global
rendering task 60 times per second that will check if any documents
need a style/layout/paint update.
That is a great simplification of our repaint scheduling model. Before
we had:
- Optional timer that schedules animation updates 60 hz
- Optional timer that schedules rAF updates
- PaintWhenReady state to schedule a paint if navigable doesn't have a
rendering opportunity on the last event loop iteration
Now all that is gone and replaced with a single timer that drives
repainting at 60 hz and we don't have to worry about excessive repaints.
In the future, hard-coded 60 hz refresh interval could be replaced with
CADisplayLink on macOS and similar API on linux to drive repainting in
synchronization with display's refresh rate.
update_layout() need to be invoked before checking if layout node is
present, because layout not being updated might be the reason why layout
node doesn't exist yet.
Previously, we set the "needs style update" flag to false at the
beginning of recomputing the style. This meant that if any code within
the cascade set this flag to true, then we would end style computation
thinking the element still needed its style updating. This could occur
when starting a transition, and would make TreeBuilder crash.
By ensuring that we always set the flag to false at the very end of
style computation, this is avoided, along with any similar issues - I
noticed a comment in `Animation::cancel()` which sounds like a
workaround was needed for a similar problem previously.
We now use the "report an exception" AO when a script has an execution
error. This has mostly replaced the older "report the exception" AO in
various specifications. Using this newer AO ensures that
`window.onerror` is invoked when a script has an execution error.
When an element is invalidated, it's possible for any subsequent sibling
or any of their descendants to also need invalidation. (Due to the CSS
sibling combinators, `+` and `~`)
For DOM node insertion/removal, we must also invalidate preceding
siblings, since they could be affected by :first-child, :last-child or
:nth-child() selectors.
This increases the amount of invalidation we do, but it's more correct.
In the future, we will implement optimizations that drastically reduce
the number of elements invalidated.
The expensive part of creating a segmenter is doing the locale and UCD
data lookups at creation time. Instead of doing this once per text node,
cache the segmenters on the document, and clone them as needed (cloning
is much, much cheaper).
On a profile loading Ladybird's GitHub repo, the following hot methods
changed as follows:
ChunkIterator ctor: 6.08% -> 0.21%
Segmenter factory: 5.86% -> 0%
Segmenter clone: N/A -> 0.09%
Instead of trying to locate the relevant StyleSheetList on style element
removal from the DOM, we now simply keep a pointer to the list instead.
This fixes an issue where using attachShadow() on an element that had
a declarative shadow DOM would cause any style elements present to use
the wrong StyleSheetList when removing themselves from the tree.
This patch implements `Range::getClientRects` and
`Range::getBoundingClientRect`. Since the rects returned by invoking
getClientRects can be accessed without adding them to the Selection,
`ViewportPaintable::recompute_selection_states` has been updated to
accept a Range as a parameter, rather than acquiring it through the
Document's Selection.
With this change, the following tests now pass:
- wpt[css/cssom-view/range-bounding-client-rect-with-nested-text.html]
- wpt[css/cssom-view/DOMRectList.html]
Note: The test
"css/cssom-view/range-bounding-client-rect-with-display-contents.html"
still fails due to an issue with Element::getClientRects, which will
be addressed in a future commit.
DOM nodes that didn't have a layout node before being removed from the
DOM are not going to change the shape of the layout tree after being
removed.
Observing this, we can avoid a full layout tree rebuild on some DOM node
removals.
This avoids a bunch of tree building work when loading https://x.com/
Computing the "contained text auto directionality" is now its own
algorithm, with an extra parameter, and is additionally called from
step 2.1.3.2 instead of calling "auto directionality".
Before this change, a formatting context was responsible for layout of
absolutely positioned boxes whose FC root box was their parent (either
directly or indirectly). This only worked correctly when the containing
block of the absolutely positioned child did not escape the FC root.
This is because the width and height of an absolutely positioned box are
resolved based on the size of its containing block, so we needed to
ensure that the containing block's layout was completed before laying
out an absolutely positioned box.
With this change, the layout of absolutely positioned boxes is delayed
until the FC responsible for the containing block's layout is complete.
This has affected the way we calculate the static position. It is no
longer possible to ask the FC for a box's static position, as this FC's
state might be gone by the time the layout for absolutely positioned
elements occurs. Instead, the "static position rectangle" (a concept
from the spec) is saved in the layout state, along with information on
how to align the box within this rectangle when its width and height are
resolved.