FIXME: Rendering modifications to a list is sometimes not pixel-perfect
vs. reference (likely a bug). After this is fixed, screenshot
tests from this commit will likely fail + can be moved to
ref tests.
The following tests also expose bugs before this PR:
- Layout/input/ol-render-item-values.html: negative ordinal values
- Layout/input/ol-render-deep-hybrid-list-item-list.html: ordinals
deep into the list owner subtree
`Element::ordinal_value` is called for every `li` element in
a list (ul, ol, menu).
Before:
`ordinal_value` iterates through all of the children of the list
owner. It is called once for each element: complexity $O(n^2)$.
After:
- Save the result of the first calculation in `m_ordinal_value`
then return it in subsequent calls.
- Tree modifications are intercepted and trigger invalidation
of the first node's `m_ordinal_value`:
- insert_before
- append
- remove
Results in noticeable performance improvement rendering' large
lists: from 20s to 4s for 20K elements.
Before:
`is<HTMLOLListElement>` and other similar calls in this commit
are resolved to `dynamic_cast`, which incurs runtime overhead
for resolving the type. The Performance hit becomes apparent
when rendering large lists. Callgrind analysis points to a
significant performance hit from calls to `is<...>` in
`Element::list_owner`.
Reference: Michael Gibbs and Bjarne Stroustrup (2006) Fast dynamic
casting. Softw. Pract. Exper. 2006; 36:139–156
After:
Implement inline `fast_is` virtual method that immediately
resolves the type. Results in noticeable performance improvement
2x-ish for lists with 20K entries.
Bonus: Convert starting value for LI elements to signed integer
The spec requires the start attribute and starting value to be
"integer". Firefox and Chrome support a negative start attribute.
FIXME: At the time of this PR, about 134 other objects resolve
`is<...>` to `dynamic_cast`. It may be a good idea to coordinate
similar changes to at least [some of] the ones that my have impact
on performance (maybe open a new issue?).
The spec assumes that we only store values against expanded longhands,
there are however limited circumstances where we store against
shorthands directly in addition to the expanded longhands. For example
if the value of the shorthand is unresolved we store an
UnresolvedStyleValue against the shorthand directly and a
PendingSubstitutionStyleValue against each of the longhands.
This commit updates the logic so that in the case we serialize a
shorthand directly we should also mark it's longhands as serialized to
avoid serializing them separately.
This also avoids the scenario where we tried to create and serialize a
ShorthandStyleValue with PendingSubstitutionStyleValue longhands, so we
can remove the check and related FIXME for that.
Fixes at least three WPT test that were previously timing out:
- html/semantics/embedded-content/media-elements/error-codes/error.html
- html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html
- html/semantics/embedded-content/the-video-element/video_crash_empty_src.html
Skia's SkColorSpace::Make() doesn't seem to like ICC v2 profiles
containing table-based L* transfer curves. Now we use
skcms_ApproximateCurve() to convert these tables to parametric curves
that Skia supports in case Skia's SkColorSpace::Make() fails.
For zlib is not necessarily an error state but the web standards do not
support this feature and the WPT tests explicitly check for this case
to be handled as an error.
If we find ourselves in a situation where zlib can't make any progress,
we don't have any more data to feed in and no output has been produced,
we need to raise an error as the compressed data is incomplete.
This used to lead to an infinite busy loop where we keep calling
zlib to decompressed but is not able. This causes the promise on the
read side of the transformer to never fulfill.
This gives us at least 24 more WPT tests :)
GCC 16 trunk has started diagnosing calls to `__has_trivial_destructor`
if the destructor is inaccessible. At the same time, they added a
Clang-compatible `__is_trivially_destructible` built-in trait, so let's
just use that.
We run these steps when focusing with a mouse pointer, and it seems
sensible to implement the same behavior for keyboard navigation so we
e.g. correctly unwind the previous focus chain.
Once an event loop manager is installed, we want to be sure we only use
that manager in the current process going forward. Mixing event loop
implementations can only cause problems.
More to the point, this ensures that we have installed the AppKit or Qt
event loop managers before the first time EventLoopManager::the() is
invoked. Now that we defer this installation until we know whether we
are running headlessly, we want to be extra sure that we have done so
before any services using the event loop have started.
When we have an unresolved value for a shorthand (e.g. `border-style:
var(--border-style)`, `keyframe_values` will contain an
`UnresolvedStyleValue` for the shorthand and
`PendingSubstitutionStyleValue`s for each of it's longhands.
When we come across the shorthand's `UnresolvedStyleValue` we will
resolve the value and set all of the relevant longhands.
If the longhand's `PendingSubstitutionStyleValue` was processed after
(which isn't always the case as the iteration order depends on a
HashMap) would overwrite the correctly resolved longhand.
To avoid this we just skip any `PendingSubstitutionStyleValue`s we come
across and rely on the resolution of the shorthand to set those
properties.
Resolves a crash @tcl3 was experiencing when adding a new
"border-image-repeat" property.
Without these fixes, RequestServer was likely to crash if the client
crashed (e.g. WebContent). This was because there was no error handling
for when writing to the client failed.
This is particularly an issue because RequestServer has shared
instances, so it would then crash every other client of RequestServer.
Then, because another RequestServer instance is not currently spun up,
it becomes impossible to start any clients that need a RequestServer
instance. Recreating a RequestServer should also be handled, but that's
not in the scope of this change.
We can tell curl that we failed to write data to the client and that
the request should be aborted by returning `CURL_WRITEFUNC_ERROR` from
the write callback.
It is also possible for requests to be destroyed with buffered data,
which is normal to happen if the client disappears
(i.e. ConnectionFromClient is destroyed) or the request is cancelled by
the client. We log a warning in case this is not expected, to assist
with debugging related issues.