The existing rebaseline script is a bit limiting in that it can only
rebaseline a single test at a time. When making sweeping changes, this
patch will let us rebaseline any number of tests at once.
For example, in the following abbreviated test HTML:
<span>some text</span>
<script>println("whf")</script>
We would have to craft the expectation file to include the "some text"
segment, usually with some leading whitespace. This is a bit annoying,
and makes it difficult to manually craft expectation files.
So instead of comparing the expectation against the entire DOM inner
text, we now send the inner text of just the <pre> element containing
the test output when we invoke `internals.signalTextTestIsDone`.
There is an issue where gifs with many frames cannot be loaded, as each
bitmap is sent over IPC using a separate file descriptor, and there is
limit on the maximum number of descriptors per IPC message. Thus, trying
to load gifs with more than 64 frames (the current limit) causes the
image decoder process to die.
This commit introduces the BitmapSequence class, which is a thin wrapper
around the type Vector<Optional<NonnullRefPtr<Gfx::Bitmap>>> and
provides an IPC encode/decode routine that collates all bitmap data into
a single buffer so that only a single file descriptor is required per
IPC transfer, even if multiple frames are being sent.
Previously, if you ran with a relative path, then everything would run
fine except that the test name would be blank in the output, eg:
1/1234:
instead of:
1/1234: Text/input/canvas/export.html
Multiple font properties are either the `normal` keyword or some
non-keyword value, so this lets us avoid some boilerplate for those, at
the cost of the existing `none` users having marginally more verbose
code.
This is a special form of `<string>` so doesn't need its own style value
type. It's used in a couple of font-related properties. For completeness
it's included in ValueType.
Two font properties, font-feature-settings and font-variation-settings,
contain a list of values that are an `<opentype-tag>` followed by a
single value. This class is intended to fill both roles.
StyleComputer is responsible for assigning animation targets, so we
have to make sure there are no pending style updates before querying
animations of an element.
This change also introduces a version of getAnimations() that does not
check style updates and used by StyleComputer to avoid mutual recursion.
The HTML tokenizer specification says that we're supposed to do this
when leaving the Attribute name or when emitting the token, as
appropriate.
Hopefully 'as appropriate' can mean only when emitting the token, as
that's the easiest place to insert this logic without complicating the
tokenizer any more.
Similar to script execution, this spins the WebDriver process until the
action is complete (rather than spinning the WebContent process, which
we've seen result in deadlocks).
This implements execution of the pointer up, pointer down, and pointer
move actions.
This isn't 100% complete. Pointer move actions are supposed to break
the move into iterations over the specified duration, which we currently
do not do.
In particular, we need to convert web element references to the actual
element. The AO isn't fully implemented because we will need to work out
mixing JsonValue types with JS value types, which currently isn't very
straight forward with our JSON clone algorithm.
This is only used for finding font directories for now, but having a
convenient function for it means if anyone needs to use XDG_DATA_DIRS
in future, they're less likely to implement it themselves and miss the
case of it being present but empty.
We also now canonicalize the data directory paths, as we do for the
other standard paths.
The XDG spec repeatedly says, for example:
> If $XDG_DATA_HOME is either not set or empty, a default equal to
$HOME/.local/share should be used.
- https://specifications.freedesktop.org/basedir-spec/latest/index.html
It's rare in practice, but does happen, for example in #1507 where we
would fail to find any system fonts if `XDG_DATA_DIRS` was blank.
This code now treats whitespace-only variables as empty too, which may
be overkill, but seems better to me than not doing so.
We had numerous NiH-based implementations of audio formats and metadata
that we now no longer need because we either don't make use of the code,
or we replaced its implementation by FFmpeg.
This loader supports whatever format libavformat and libavcodec can
handle. Currently only seekable streams are supported, and we still have
some limitations as to the number of channels and sample format.
Plays all non-streaming audio files at:
https://tools.woolyss.com/html5-audio-video-tester/
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.
This has no visible effect, but internally it's also highlighting any
CSS and JS embedded in the page, which will be made use of later. We'll
also be able to use this code for highlighting CSS or JS files directly
in the future.
It's not a perfect fit - the syntax highlighters give specific styles to
their spans, which we then ignore and just use their data integer to
figure out which CSS class to give to the span. It feels cleaner to me
to produce HTML styled that way, instead of every token having
`style="color: ...; font-weight: ...; text-decoration: ...;"` set on
it.
Most of this new `to_html_string()` code is adapted from Serenity's
`TextEditor::paint_event()`, so it should be pretty solid.
The code previously ensured that JS/CSS tokens did not share values with
the HTML tokens, but still let them share values with each other. The
numbers chosen (1000 and 2000) are somewhat arbitrary, but give us
plenty of room to avoid overlaps.
Fixes crashing on https://playbiolab.com/ in
VERIFY(page.client().is_ready_to_paint()) caused by attempting to start
the next repaint before the ongoing repaint is done.
This is an ad-hoc implementation that resolves the ready() promise once
the document and all fonts collected by the style computer are done
loading. A spec-compliant implementation would include creating a proxy
CSS::FontFace for each @font-face and correctly implementing the
specification steps for font fetching, but we are far from there yet.
This hackish implementation should yield good WPT progress because it
will actually start waiting for the Ahem font to load before capturing
layout measurements. For example, it makes
https://wpt.live/css/css-grid/abspos/positioned-grid-descendants-001.html
go from 0/100 to 36/100 passing subtests.
We were generating click events always using the primary mouse button
instead of the provided button, and with the buttons field set to that
provided button.
After closing a window, it is the client's job to switch to another
window before executing any other command. Currently, we will crash if
that did not happen when we try to send an IPC to a window handle that
we no longer hold. This patch makes us return a "no such window" error
instead.
The exceptions to this new check are the "Switch to Window" and "Get
Window Handles" commands.
This is what the spec tells us to do:
The root element’s display type is always blockified,
and its principal box always establishes an independent
formatting context.
Additionally, a display of contents computes to block
on the root element.
Spec link: https://drafts.csswg.org/css-display/#rootFixes#1562
CSS Fonts level 4 renames font-stretch to font-width, with font-stretch
being left as a legacy alias. Unfortunately the other specs have not yet
been updated, so both terms are used in different places.
It's possible to resolve box's height without doing inner layout, when
computed value is not auto. Doing that fixes height resolution, when box
with percentage height has containing block with percentage height.
Before:
- resolve used width
- layout box's content
- resolve height
After:
- resolve used width
- resolve height if treated as not auto
- layout box's content
- resolve height if treated as auto
When a property is a "legacy name alias", any time it is used in CSS or
via the CSSOM its aliased name is used instead.
(See https://drafts.csswg.org/css-cascade-5/#legacy-name-alias)
This means we only care about the alias when parsing a string as a
PropertyID - and we can just return the PropertyID it is an alias for.
No need for a distinct PropertyID for it, and no need for LibWeb to
care about it at all.
Previously, we had a bunch of these properties, which misused our code
for "logical aliases", some of which I've discovered were not even
fully implemented. But with this change, all that code can go away, and
making a legacy alias is just a case of putting it in the JSON. This
also shrinks `StyleProperties` as it doesn't need to contain data for
these aliases, and removes a whole load of `-webkit-*` spam from the
style inspector.
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.
Rather than checking the avcodec version in CMake, check it using the
avcodec version macros in the only source file that needs to know about
the AVFrame API/ABI change in version 59.24.100. This is friendlier to
other build systems that would rather avoid configure time checks.
We are currently returning a JSON object of the form:
{
"name": "element-6066-11e4-a52e-4f735466cecf",
"value": "foo"
}
Instead, we are expected to return an object of the form:
{
"element-6066-11e4-a52e-4f735466cecf": "foo"
}
Very similar to commit e5877cda61.
By sending as much data as we can in a single write, we see a massive
performance improvement on WPT tests that hammer WebDriver with errors.
On my Linux machine, this reduces the runtime of:
/webdriver/tests/classic/perform_actions/invalid.py
from 45-60s down to 3-4s.
We must send a Cache-Control header, which then also requires that we
respond with an HTTP/1.1 response (the Pragma cache option is HTTP/1.0).
We should also send the Content-Type header using the same casing as is
written in the WebDriver spec (lowercase).
Both of these are explicitly tested by WPT.
Instead of creating a unique new prototype shape every time a function
object is instantiated, we now keep one cached with the intrinsics.
This avoids a whole lot of shape allocations, reducing GC pressure.
Instead of converting images to alpha masks on the CPU, we now delegate
that work to the GPU if possible, by way of SkSL shaders.
This noticeably speeds up https://vercel.com/ which has a ton of SVG
masking going on. The old implementation used 15% of CPU time when
loading the page, this one uses basically none.
I originally believed that this could never receive a null URL and the
spec was inaccurate, but it seems like it can indeed.
I don't have a distilled test, but this makes logging in with GitHub
work on https://v0.dev/
The spec allows us to either treat them as part of the UA origin, or as
its own origin before author styles. This second behaviour turns out to
be what we are currently doing, which is nice!
Funnily enough this was clarified in the spec barely a month after this
original comment was written. :^)
`revert` is supposed to revert to the previous cascade origin, but we
previously had it reverting to the previous layer. To support both,
track them separately during the cascade.
As part of this, we make `set_property_expanding_shorthands()` fall back
to `initial` if it can't find a previous value to revert to. Previously
we would just shrug and do nothing if that happened, which only works
if the value you want to revert to is whatever is currently in `style`.
That's no longer the case, because `revert` should skip over any layer
styles that have been applied since the previous origin.
It's difficult to know what we need to implement if we silently ignore
these endpoints. Let's log the endpoints and their parameters, and clean
up the wall of FIXME comments to be easier to grok.
WPT uses Python's http.client.HTTPConnection to send/receive WebDriver
messages. For some reason, on Linux, we see an ~0.04s delay between the
WPT server receiving the WebDriver response headers and its body. There
are tests which make north of 1100 of these requests, which adds up to
~44s.
These connections are almost always going to be over localhost and able
the be sent in a single write. So let's send the response all at once.
On my Linux machine, this reduces the runtime of /cookies/name/name.html
from 45-60s down to 3-4s.
If we don't recognize a given transition-property value as a known CSS
property (one that we know about, not necessarily an invalid one),
we should not extrapolate the other transition-foo values for it.
Fixes#1480
https://github.com/whatwg/console/pull/240 is an editorial change to use
the term "implementation-defined" more consistently. This seems to be
the only instance in the spec text which we quote verbatim.
This mainly uses forward declarations as appropriate for input element
related files. This reduces the number of targets being built when we
change HTMLInputElement.h from 430 to 44.
Previously, we would crash when attempting to establish a web socket
connection from inside a worker, as we were assuming that the ESO's
global object was a `Window`.
Previously, some otherwise unimplemented WebDriver endpoints were
indicating that they had executed successful, this was causing a large
number of Web Platform Tests to time out when they should have failed.
The thread pool test is currently flakey and takes over 2 minutes to run
on CI. It also currently has no users now that RequestServer uses curl,
so let's just remove it for now. If we need it in the future, we can
revive it from git history.
If we decide to fetch another linked resource, we don't care about the
earlier fetch and can safely abort it.
This fixes an issue on GitHub where we'd load the same style sheet
multiple times and invalidate style for the entire document every time
it finished fetching.
By aborting the ongoing fetch, no excess invalidation happens.
As useful as they may be to web developers, :has() selectors complicate
the style invalidation process quite a lot.
Let's have StyleComputer keep track of whether they are present at all
in the current set of active style sheets. This will allow us to
implement fast-path optimizations when there are no :has() selectors.
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%
We now expand shorthands into their respective longhand values when
assigning to a shorthand named property on a CSSStyleDeclaration.
We also make sure that shorthands can be round-tripped by correctly
routing named property access through the getPropertyValue() AO,
and expanding it to handle shorthands as well.
A lot of WPT tests for CSS parsing rely on these mechanisms and should
now start working. :^)
Note that multi-level recursive shorthands like `border` don't work
100% correctly yet. We're going to need a bunch more logic to properly
serialize e.g `border-width` or `border` itself.
The algorithm for starting a transition requires us to examine the
before-change and after-change values of the property, without taking
any current animations into account.
..and delay static position calculation in IFC until trailing
whitespace are removed, because otherwise it's not possible to correctly
calculate x offset.
Containing block for abspos grid items depends on their grid placement:
- if element has definite grid position, then corresponding grid area
should be used as a containing block
- if element does not have definite grid position, then padding edge of
grid container should be used as a containing block
So offset should be adjusted for paddings only for boxes without
definite grid position.
The web server for WPT has a tendency to just disconnect after sending
us a resource. This makes curl think an error occurred, but it's
actually still recoverable and we have the data.
So instead of just bailing, do what we already do for other kinds of
resources and try to parse the data we got. If it works out, great!
It would be nice to solve this in the networking layer instead, but
I'll leave that as an exercise for our future selves.
This fixes an issue where document.write() with only text input would
leave all the character data as unflushed text in the parser.
This fixes many of the WPT tests for document.write().
...instead of directly mutating Gfx::Bitmap.
This change is preparation for using GPU-backend for canvas painting
where direct mutating of backing storage that bypasses painter is no
longer possible.
Our current text iterator is not aware of multi-code point graphemes.
Instead of simply incrementing an iterator one code point at a time, use
our Unicode grapheme segmenter to break text into fragments.
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.
When a block container has `clear` set and some clearance is applied,
that clearance prevents margins from adjoining and therefore resets
the margin state. But when a floating box has `clear` set, that
clearance only goes between floating boxes so should not reset margin
state. BlockFormattingContexts already do that correctly, and this PR
changes InlineFormattingContext to do the same.
Fixes#1462; adds reduced input from that issue as test.
This is not that easy to use for test developers, as forgetting to set
the url back to its original state after testing your specific API will
cause future navigations to fail in inexplicable ways.
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.
The current min/max zoom levels are supposed to be: 30% and 500%.
Before, due to floating point error accumulation in incremental addition
of zoom-step into zoom-level, one extra zoom step would get allowed,
enabling user to zoom 20%-to-510%.
Now, using rounding, the intermediate zoom-level values should be as
close to the theoretical value as FP32 can represent. E.g. zoom-level of
70% (theoretical multiplier 0.7) is 0.69... .
The IPCs to request a page's text, layout tree, etc. are currently all
synchronous. This can result in a deadlock when WebContent also makes
a synchronous IPC call, as both ends will be waiting on each other.
This replaces the page info IPCs with a single, asynchronous IPC. This
new IPC is promise-based, much like our screenshot IPC.
If we already destroyed our timer during destruction, and then curl
tries to flush its timeouts when we tear down the multi, we can just
ignore the timer callbacks.
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/
This makes a big difference on macOS, where the default buffer size
for local sockets is 8 KiB. With bigger buffers, we don't have to
block on IPC nearly as often.
To prevent deadlocks when both IPC peers are trying to send to each
other but both sides have too much in their buffer already, we now
move the send operation to a secondary thread where it can block until
the peer is able to handle it.
Attributes have a max value length of 1024. So we theoretically need to
support values in the range -${"9".repeat(1023)} to ${"9".repeat(1024)}.
These obviously do not fit in an i64, so we were previously failing to
parse the attribute.
We will now cap the parsed value to the numeric limits of an i64, after
ensuring that the attribute value is indeed a number.
We were only looking at the current top-level navigable and its children
when searching for the specified window handle. We need to search *all*
known navigables if the handle belongs to a window not in the current
tree.
We very much assume that the SQL storage backend runs in a singleton
process. When this is not the case, and multiple UI processes try to
write to the database at the same time, one of them will fail.
Since --force-new-process is a testing mode flag, let's just disable the
SQL backend when that flag is present.
Previously, attempting to get the computed value for a
grid-template-rows or grid-template-columns property would cause a crash
if the element had no associated paintable.
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".
...because calculate_inner_width() assumes layout state has resolved
paddings that could be used to account for "box-sizing: border-box".
Fixes regression introduced in 5f74da6ae8
Function is defined as `round(<rounding-strategy>?, A, B?)`
With this change resolved type is `typeof(resolve(A))`, instead of
`typeof(A)`.
For example `round(up, 20%, 1px)` with 200px percentage basis is now
correctly resolved in 40px instead of 40%.
Progress on https://www.notion.so/ landing page.
Before this change, each BFC child that established an FC root was laid
out at least twice: the first time to perform a normal layout, and the
second time to perform an intrinsic layout to determine the automatic
content height. With this change, we avoid the second run by querying
the formatting context for the height it used after performing the
normal layout.
The `calculate_inner_width()` and `calculate_inner_height()` resolve
percentage paddings using the width returned by
`containing_block_width_for()`. However, this function does not account
for grids where the containing block is defined by the grid area to
which an item belongs.
This change fixes the issue by modifying `calculate_inner_width()` and
`calculate_inner_height()` to use the already resolved paddings from the
layout state. Corresponding changes ensure that paddings are resolved
and saved in the state before box-sizing is handled.
As a side effect, this change also improves abspos layout for BFC where
now paddings are resolved using padding box of containing block instead
of content box of containing block.
Fixes yet another case of GFC bug, where Node::containing_block() should
not be used for grid items, because their containing block is grid area
which is not represented in layout tree.