Compare commits

...

2281 Commits

Author SHA1 Message Date
Timothy Flynn
5e40db5a17 AK: Remove some now-unnecessary workarounds for simdutf base64 usage
Some checks failed
CI / Lagom (arm64, Sanitizer_CI, false, macOS, macos-15, Clang) (push) Has been cancelled
CI / Lagom (x86_64, Fuzzers_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Has been cancelled
CI / Lagom (x86_64, Sanitizer_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, GNU) (push) Has been cancelled
CI / Lagom (x86_64, Sanitizer_CI, true, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Has been cancelled
Build Dev Container Image / build (push) Has been cancelled
Package the js repl as a binary artifact / build-and-package (arm64, macOS, macOS-arm64, macos-15) (push) Has been cancelled
Package the js repl as a binary artifact / build-and-package (x86_64, Linux, Linux-x86_64, blacksmith-8vcpu-ubuntu-2404) (push) Has been cancelled
Run test262 and test-wasm / run_and_update_results (push) Has been cancelled
Lint Code / lint (push) Has been cancelled
Label PRs with merge conflicts / auto-labeler (push) Has been cancelled
Push notes / build (push) Has been cancelled
Close stale PRs / stale (push) Has been cancelled
Nightly Windows / CI (push) Has been cancelled
2025-06-01 08:03:00 -04:00
Timothy Flynn
3693fd5caa Meta: Update simdutf to version 7.3.0 2025-06-01 08:03:00 -04:00
Timothy Flynn
d9d87d4816 Meta: Update libjxl to version 0.11.1#1
This includes a CMake fix that we added for Ladybird.
2025-06-01 08:03:00 -04:00
Timothy Flynn
0f2bcd26c4 Meta: Update curl to version 8.14.0 2025-06-01 08:03:00 -04:00
Timothy Flynn
2205177d15 Meta: Update vcpkg baseline 2025-06-01 08:03:00 -04:00
Aliaksandr Kalenik
4b4d960cba LibWeb: Cancel previous animation if new animation-name is "none"
"none" value should be interpreted as "no animation" to trigger the path
that cancels previous animation if it exists.
2025-06-01 05:02:12 +02:00
Timothy Flynn
985434ea10 headless-browser: Allow running LibWeb tests without specifying a path
Especially on new setups, it is handy for `headless-browser --run-tests`
to "just work". Anyone using ladybird.py will have LADYBIRD_SOURCE_DIR
set in their environment already.
2025-06-01 10:34:30 +12:00
Shannon Booth
bc4317be20 LibWeb/HTML: Handle failure determining mime type fetching module script
Fixes crash in WPT test:

https://wpt.live/html/semantics/scripting-1/the-script-element/css-module/content-type-checking.html
2025-05-31 09:15:52 -04:00
Shannon Booth
caf959f06c LibWeb/FileAPI: Handle an aborted stream in Blob::get_stream() close
The streams AO that we were calling to close the stream would assert
if it was not in a readable state. This version of close is exported
publicly in the streams specification, and properly handles this
situation.

Fixes a crash in the imported test, and happens to fix some others!
2025-05-31 09:12:57 -04:00
Timothy Flynn
667a568526 Meta: Add compiler arguments to the debug build mode 2025-05-30 20:06:15 -04:00
Andrew Kaster
6f9e56870e CMake: Exclude GlobalFontConfig.h from autogenerated clang module
This header file is never included by any other headers, and including
it would require adding the fontconfig include paths to the swift
interop header generation, which is not desirable.
2025-05-30 15:21:17 -06:00
Andrew Kaster
17b7f192c4 LibGfx: Add a strict CMake check for the libpng apng patch 2025-05-30 15:21:07 -06:00
Andrew Kaster
8f0dad0898 CMake: Use static libraries for try_compile() in libfuzzer builds 2025-05-30 15:21:07 -06:00
Andrew Kaster
645eac1734 CI: Use new name for macOS JS artifact in js-benchmarks workflow
This was missed in 1a0b83a59f
2025-05-30 14:20:44 -06:00
Timothy Flynn
3786d56814 Meta: Remove msbuild presets
Let's just support ninja for simplicity. The msbuild presets are
significantly slower anyhow.
2025-05-30 13:52:51 -04:00
Andrew Kaster
1a0b83a59f CI: Rename macOS js REPL artifact to match name of tgz
We haven't built a universal binary in over 11 months. The name is
confusing, and actually breaks esvu on macOS. The fact that nobody
has complained suggests that this is not a common use case..
2025-05-30 11:28:06 -06:00
Andrew Kaster
30fe721a3d CMake: Set a higher default CMAKE_OSX_DEPLOYMENT_TARGET with Swift
We have tests that require 15.0 without checking for availability.
2025-05-30 12:54:12 -04:00
Andrew Kaster
68bba89dc3 CMake: Set macOS deployment target for vcpkg ports to match our build
Without this, ports get built with whatever default is there from the
toolchain, and we get all sorts of linker warnings about a mismatch.
2025-05-30 12:54:12 -04:00
Timothy Flynn
0958c5f508 Meta: Provide compiler jobs as a command line argument
On my Linux machine with 32 cores, ninja actually defaults to 34 jobs.
By defaulting ourselves to multiprocessing.cpu_count(), we actually
decrease the number of jobs used.
2025-05-30 12:03:38 -04:00
Timothy Flynn
e6938e11b0 Meta: Inspect the host compiler only when needed
We don't need to pick a host compiler every time ladybird.py is invoked.
We only need to do so when configuring the Build directory.

This shaves about 10ms off an invocation of `ladybird.py build` on my
machine, going from ~170ms to ~160ms.
2025-05-30 12:03:38 -04:00
Timothy Flynn
16743ee9d9 Meta: Invoke ninja directly instead of cmake --build
This shaves about 10ms off an invocation of `ladybird.py build` on my
machine, going from ~180ms to ~170ms.
2025-05-30 12:03:38 -04:00
InvalidUsernameException
52ba40f161 Tests/LibWeb: Fix flaky css background test
This test was introduced in 70b52e0994 and
was flaky in CI and on my local machine.
2025-05-30 12:03:25 -04:00
Andrew Kaster
0f81f021ce LibWeb: Clean up main thread promise when exiting RenderingThreads
Not cleaning these up by rejecting or resolving the promise causes
the main thread to try to reject them at EventLoop::exit() time.

If the RenderThread has already been destroyed by then, we get into
use-after-free territory and segfault.
2025-05-30 16:18:23 +02:00
Aliaksandr Kalenik
3178679f0b LibWeb: Implement CSS transitions support for pseudo elements
We already had all necessary things for pseudo elements support in place
except ability to save transition properties in Animatable. This commit
adds the missing part.
2025-05-30 15:48:16 +02:00
Timothy Flynn
9d0c307341 CI: Add a quoteless cache restore key for GitHub runners
The way we echo the cache keys for output variables strips these quotes.
So when we save the caches at the end of CI, the keys are sans quotes.

This patch adds an extra cache restore key without quotes to allow jobs
to fetch their own caches again. This will become moot once all runners
are able to use the Blacksmith cache action.
2025-05-30 09:03:35 -04:00
Timothy Flynn
877687d1f6 Meta: Make the ladybird.py test pattern argument positional
Restores API compatibility with the old ladybird.sh.
2025-05-30 06:40:56 -04:00
Timothy Flynn
6345ebb78c Meta: Don't assume all build commands have a target
For example, the "test" and "vcpkg" build commands do not.
2025-05-30 06:40:56 -04:00
Andreas Kling
61285ffbee LibWeb: Add document null check in ...navigable_target_name_property_set 2025-05-30 10:13:25 +02:00
Andreas Kling
2eea8894a1 LibWeb: Don't crash on named property access on detached window
In WindowProxy.[[Get]] it's not guaranteed that the current principal
global object has an associated document at the moment. This may happen
if a script is continuing to execute while a navigation has been
initiated.

Because of that, we can't blindly dereference the active document
pointer, so this patch adds a null check.
2025-05-30 10:13:25 +02:00
InvalidUsernameException
456608cf03 Tests: Fix flaky test
This flake was introduced in 164afdcc59.
2025-05-30 00:12:27 -04:00
Lucien Fiorini
8b08162942 js: Make print variadic for consistency with other repls 2025-05-29 17:33:26 -06:00
Lucien Fiorini
81e84c8273 js: Add option to disable quotes around strings 2025-05-29 17:33:26 -06:00
Timothy Flynn
f46f9b0f02 Meta: Restore default "build everything" behavior in ladybird.py
By default, we want `ladybird.py build` to build everything. We were
previously defaulting to only building the Ladybird target.

We now only fall back to the Ladybird target for commands that run a
program. So `ladybird.py run` will build and run Ladybird.
2025-05-29 16:24:17 -04:00
Timothy Flynn
aa0fcc67b3 Meta: Tentatively support BSD distributions in ladybird.py
Support was unknowingly dropped when porting ladybird.sh to ladybird.py.
This tentatively restores this support, but is untested on a BSD system.
2025-05-29 16:24:17 -04:00
Timothy Flynn
7ce88eb4cd Everywhere: Document use of ladybird.py over ladybird.sh 2025-05-29 16:24:17 -04:00
Timothy Flynn
6ac729e03d Meta: Replace ladybird.sh contents with invocation to ladybird.py
All features supported by ladybird.sh should now work in ladybird.py.
Let's forward invocations and warn that ladybird.sh will be removed.
2025-05-29 16:24:17 -04:00
Timothy Flynn
f2eaf1e57b Meta: Use new run_command utility to invoke subprocesses
As opposed to just running subprocess.check_call, our `run_command`
utility handles e.g. ctrl+c to avoid spamming the terminal with
KeyboardInterrupt stack traces.
2025-05-29 16:24:17 -04:00
Timothy Flynn
a5bfb686f4 Meta: Integrate find_compiler.py into ladybird.py 2025-05-29 16:24:17 -04:00
Timothy Flynn
3d0fdaacff Meta: Migrate find_compiler.sh logic to a python script
This will allow us to re-use this logic from within other python
scripts. The find_compiler.sh script still exists, as it is used by
some other bash scripts. The pick_host_compiler() function will now
execute find_compiler.py and store its result in $CC and $CXX.

Note that the python script supports Windows.
2025-05-29 16:24:17 -04:00
Timothy Flynn
8e792cd094 Meta: Support python 3.9 in ladybird.py
This is the default python version on macOS, so let's support it since
it is trivial for now. Using "str | None" as a type annotation is only
supported in python 3.10 or later.
2025-05-29 16:24:17 -04:00
Timothy Flynn
a76e880dfe Meta: Extract platform detection utilities to their own file
This will be needed by other scripts.

To do so, this patch gives up on the importlib method of importing
packages. I tried extracting this helper to e.g. __init__.py, but the
python runtime was unable to find the imported symbols.
2025-05-29 16:24:17 -04:00
Timothy Flynn
872a112cad Meta: Add SPDX license identifier to ladybird.py and BuildVcpkg.py 2025-05-29 16:24:17 -04:00
Timothy Flynn
23855bd412 LibWebView: Do not make the client bitmap shareable for screenshots
Not sure what the issue is here, but it seems to cause very incorrect
screenshots on macOS. In any case, it's wasted computation.
2025-05-29 16:24:08 -04:00
InvalidUsernameException
164afdcc59 LibWeb: Ensure scroll offset is applied to mask-images
When recording the display list for a stacking context, the following
operations (relevant to this bug) happened:
* push a stacking context
  * as part of that push a None-value to the scroll frame id stack
* apply filters
* apply masking
* paint recursively

This meant that mask-images were always recorded without scroll frame
id, causing them to be painted without any scroll offset. As a result
mask-images would break as soon as the website using them was scrolled.

Instead, push to the scroll frame id stack later to solve the problem:
* push a stacking context
* apply filters
* apply masking
* push a None-value to the scroll frame id stack
* paint recursively
2025-05-29 22:02:07 +02:00
Callum Law
ed65d5b342 LibWeb: Serialize CSS declarations as shorthands where applicable
When serializing CSS declarations we now support combining multiple
properties into a single shorthand property in some cases.

This comes with a healthy dose of FIXMEs, including work to be done
around supporting:
 - Nested shorthands (e.g. background, border, etc)
 - Shorthands which aren't represented by the ShorthandStyleValue type
 - Subproperties pending substitution

This gains us a bunch of new test passes, both for WPT and in-tree
2025-05-29 12:04:28 +02:00
Callum Law
94f5a51820 LibWeb: Convert white-space CSS property to shorthand
This exposed a few bugs which caused the following tests to behave
incorrectly:
- `tab-size-text-wrap.html`: This previously relied on a bug where we
  incorrectly treated `white-space: pre` as allowing text wrapping. The
  fix here is to implement the text-wrap CSS shorthand property.

- `execCommand-preserveWhitespace.html`: We don't correctly serialize
  shorthand properties. This is covered by an existing FIXME in
  `CSSStyleProperties::serialized()`

- `white-space-shorthand.html`: The last 5 subtests here fail as we
  don't correctly handle shorthand properties in
  `CSSStyleProperties::remove_property()`. This is covered by an
  existing FIXME in said function.
2025-05-29 12:04:28 +02:00
Callum Law
9d06c86fe4 LibWeb: Support shorthands as relevant_css_property for editing commands 2025-05-29 12:04:28 +02:00
Callum Law
45689936f2 LibWeb: Support shorthand properties as presentational hints 2025-05-29 12:04:28 +02:00
Callum Law
9480b1fc5c LibWeb: Parse and propagate white-space-trim CSS property 2025-05-29 12:04:28 +02:00
Callum Law
50bdd2cb85 LibWeb: Parse and propagate text-wrap-mode CSS property 2025-05-29 12:04:28 +02:00
Callum Law
ea30356fba LibWeb: Parse and propagate white-space-collapse CSS property 2025-05-29 12:04:28 +02:00
R-Goc
3989059227 Libraries/Utilities/Tests: Build and test js.exe
This commit enables building and testing js.exe for windows. Needed
libraries are built in CI, and tests for those which pass were added.
Tests for LibJS which don't require javascripttestrunner were added but
the rest need to wait for that to be ported to windows.
2025-05-29 03:26:23 -06:00
R-Goc
b0cc87c276 Utilities: Port js.exe on windows without repl
This commit allows building js.cpp on windows. The repl functionality is
ifdef'ed out. To decrease the number of ifdefs the code that runs the
repl on Linux was moved into one place. Some globals that are unused as
a result of that are markes maybe_unused. The following commit enables
building and testing js in cmake for windows.
2025-05-29 03:26:23 -06:00
R-Goc
550aace91c Meta: Add flags for compilation and testing of js
This commit adds flags necessary for compilation and testing of js.exe.
The stack size is increased to match linux.
2025-05-29 03:26:23 -06:00
R-Goc
96c197faf1 LibJS: Add minimum changes to build on Windows and run js.exe
This commit adds the minimal export macros needed to run js.exe on
windows. A followup commit is planned to move to explicit export
entirely.

A static_assert for the size of a struct is also ifdef'ed out as the
semantics around object layout and inheritance are different on MSVC abi
and the struct IteratorRecord ends up being 40 bytes not 32.
2025-05-29 03:26:23 -06:00
Andrew Kaster
e67495e141 LibCrypto: Forward declare tommath types properly on Windows 2025-05-29 03:26:23 -06:00
R-Goc
f669af3a5c LibGC: Add the minimum export macros required to link LibJS
This approach still requires the WINDOWS_EXPORT_ALL_SYMBOLS target
property, but it does let us run a lot more tests than before.
2025-05-29 03:26:23 -06:00
R-Goc
d5cb940fe0 LibGC: Use native windows allocation methods for GC blocks
This allows us to use DiscardVirtualMemory in the same way that we
use madvise with MADV_DONTNEED and MADV_FREE on Unix systems.
2025-05-29 03:26:23 -06:00
Andreas Kling
00ad2bd758 LibWeb: Use the GC::RootVector deduction guides where helpful 2025-05-29 03:46:49 +02:00
Andreas Kling
5c5283492b LibWeb: Iterate safely in HTMLSelectElement::set_value()
We can't iterate over m_cached_list_of_options and call set_selected()
in the loop, since that may end up rebuilding m_cached_list_of_options,
disrupting iteration.
2025-05-29 03:46:49 +02:00
Andreas Kling
18d17385fb LibWeb: Remove leftover debugging hack in process_top_layer_removals() 2025-05-29 03:46:49 +02:00
Andreas Kling
2afe208328 LibWeb: Iterate safely in process_top_layer_removals()
We should not remove from a container while iterating over it, since
that may disrupt iteration.
2025-05-29 03:46:49 +02:00
Andreas Kling
59d46af946 LibWeb: Iterate safely in update_animations_and_send_events()
Make copies of the animation timeline list and animations to dispatch
events at before iterating over them. This ensures that they can't be
modified during iteration.
2025-05-29 03:46:49 +02:00
Andreas Kling
32769393a8 LibWeb: Iterate safely in invalidate_style_of_elements_affected_by_has()
We move m_pending_nodes_for_style_invalidation_due_to_presence_of_has to
a local variable before iterating over it. This ensures that nothing can
be added to it while iterating.
2025-05-29 03:46:49 +02:00
Andreas Kling
d5892c7c7a LibGC: Add some deduction guides for GC::RootVector
This makes is easy to construct a RootVector from a vector or span of
references to GC objects.
2025-05-29 03:46:49 +02:00
Andreas Kling
e0e09f71be RequestServer: Don't try to self-destruct already-destroyed request 2025-05-29 03:46:49 +02:00
Aliaksandr Kalenik
c2c9348636 LibWeb: Print FIXME instead of throwing NotSupportedError in WebAudio
This allows us to browse https://pierre.co/ instead of being navigated
to error screen.
2025-05-28 20:37:35 +02:00
Aliaksandr Kalenik
36a255eedd LibWeb: Fix glitchy CSS transitions
`start_needed_transitions()` decides which animations need to be started
based on previous and current style property values. Before this change,
we were using the style value without animations applied as the
"current" value. This caused issues such as starting a new transition
from the animation’s end value when an ongoing animation was
interrupted.
2025-05-28 17:35:59 +01:00
Aliaksandr Kalenik
62739c30d9 LibWeb: Schedule required invalidations when animation effect is removed
For example, if layout affecting property is animated then once this
animation is removed we need to schduled layout invalidation.
2025-05-28 17:35:59 +01:00
Aliaksandr Kalenik
6a029fb6d9 LibWeb: Reset animated CSS properties for pseudo elements
Previously we were resetting animated properties if animation effect's
target is not a pseudo element.
2025-05-28 17:35:59 +01:00
Andrew Kaster
c5071c9025 Tests: Re-enable TestLibCoreMappedFile and TestLibCoreStream
These tests previously only ran on SerenityOS. They needed test input
location changes. The Stream tests also needed to explicitly set
SO_REUSEADDR for the tcp servers.
2025-05-27 20:34:47 -06:00
Andrew Kaster
a94605febe CI: Bump swift toolchain to main-snapshot-2025-05-26 2025-05-27 20:33:42 -06:00
Andrew Kaster
e90a0dc69c CI: Update alternatives for llvm-symbolizer on Ubuntu jobs
Swift jobs were failing a test due to the llvm-symbolizer not being
available in the default location next to the clang binary. swift.org
toolchains don't ship this tool, so LSAN suppressions were not being
applied, failing TestWOFF2.

This was hard to reproduce locally, because I have always had a set of
alternatives set up for the full suite of LLVM tools on my machine.
2025-05-27 20:33:42 -06:00
Andrew Kaster
cd333fe3e9 CI: Use Blacksmith cache action only on Blacksmith runners
Their cache action only works on their runners. For jobs that run on
other runners, we have use the default cache action. At least until they
update their cache product to work or fallback on other runners.
2025-05-27 17:42:25 -06:00
Dan Berglund
d9e90d4556 AppKit: Check availability before using macOS 15 API in TabController
This keeps the code building on older macOS versions.
2025-05-27 13:39:24 -06:00
Dan Berglund
bd3135f8d3 CMake: Set default CMAKE_OSX_DEPLOYMENT_TARGET to 14.0
This makes the build system aware of which macOS version we're
targeting, and will make it an error to newer APIs without explicitly
checking the availability.

Note that the js REPL CI job still sets the deployment target to 11.0
explicitly.
2025-05-27 13:39:24 -06:00
Callum Law
6c3ceb9284 LibWeb: Don't crash when handling invalid HTTP status codes
Example crash: https://wpt.live/fetch/h1-parsing/status-code.window.html

There is still work to make the above tests pass.
2025-05-27 12:58:08 -06:00
Timothy Flynn
24da7b006e Meta: Change the ladybird.py target to be a positional argument
This affords us some API symmetry with ladybird.sh.
2025-05-27 20:02:37 +02:00
Timothy Flynn
25666390f6 Meta: Alias the "ladybird" target to "Ladybird" in ladybird.py
We do the same thing in ladybird.sh for convenience.
2025-05-27 20:02:37 +02:00
Timothy Flynn
e7fe2d3dab Meta: Do not pass non-existing extra arguments to addr2line build step
The variadic nature of the addr2line command is currently taken by the
`addresses` option.
2025-05-27 20:02:37 +02:00
Ruben
3263b629c6 LibWeb: Correct the calculation for right float intrusion
We used to subtract the maximum right margin of any containing box,
but we want to subtract the entire right margin instead. This yielded
incorrect intrusions for right floats not placed in the root.
2025-05-27 17:31:47 +02:00
Timothy Flynn
8e5cc74eb1 LibJS: Add notation to Intl.PluralRules
This is a normative change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/a7ff535
2025-05-27 10:39:25 -04:00
Tim Ledbetter
b16f34767e LibWeb: Ensure discrete interpolated properties are non-transitionable
If a property is uses discrete interpolation and TransitionBehavior is
not set to `AllowDiscrete` that property should be non-transitionable.

This is now true for properties whose animation type is not discrete,
but the animation type falls back to discrete.
2025-05-27 13:33:29 +02:00
Jelle Raaijmakers
922bf2033f CI: Use Blacksmith's drop-in replacement for actions/cache
Their caches have better locality with their own runners and offer
higher potential throughput speeds (up to 400 MB/s).
2025-05-27 12:10:55 +02:00
Jelle Raaijmakers
090a7a90c3 CI: Switch over remaining runners to Blacksmith.sh
Everything that's not self-hosted or macOS is now pointing to
Blacksmith.sh. Nightly jobs and JS artifact builds use 8VCPU machines,
while regular integration builds & tests use 16VCPU machines.
2025-05-27 12:10:55 +02:00
Jelle Raaijmakers
8e9bf01917 CI: Rename os input to runner
This more clearly describes what the value is being used for, and avoids
some confusion between `os` and `os_name` in `lagom-template.yml`.
2025-05-27 12:10:55 +02:00
Jelle Raaijmakers
08b81b37b1 CI: Reindent inputs in lagom-template.yml 2025-05-27 12:10:55 +02:00
Jelle Raaijmakers
be766ecb30 CI: Switch over some workflows to Blacksmith.sh runners
The people over at Blacksmith.sh have generously offered usage of their
runners for our organization, so let's try to switch over some simple
workflows. The runners should be drop-in replacements.
2025-05-27 09:50:24 +02:00
Khaled Lakehal
9a071c9e89 LibWeb/HTML: Fix behavior when removing multiple from select element
This change ensures correct behavior when the `multiple` attribute is
removed from a `select` element, reducing the number of selected
`option` elements to one.

Fixes a failing WPT test:
https://wpt.live/html/semantics/forms/the-select-element/select-multiple.html
2025-05-27 18:58:31 +12:00
Shannon Booth
937994cfaa LibWeb: Make Environment's top level origin nullable
This matches the definition in the spec, and is also a step towards
removing the default constructor of URL::Origin.
2025-05-27 14:48:43 +12:00
Shannon Booth
556acd82ee LibWeb/Editing: Handle no active range in queryCommandState
Fixes a crash when this is invoked if no range is active for the
document.
2025-05-26 23:36:44 +02:00
Shannon Booth
7c7fec5e00 LibWeb/Editing: Pass normalized command name to editing AOs
As the internal algorithms perform case sensitive matching.
Fixes a crash in the included test, seen on gmail.com.
2025-05-26 23:36:44 +02:00
Rocco Corsi
70abe99bfd Tests: Add test for MimeType sniffing from filenames 2025-05-26 14:23:43 -06:00
Rocco Corsi
9281baffd8 LibCore: Recognize filenames .shellrc and CMakeLists.txt as text
There was a missing comma in the array, so these two entries were
concatenated accidentally.
2025-05-26 14:23:43 -06:00
Aliaksandr Kalenik
1647d7b34c LibJS: Use CallBuiltin for Math.tan() 2025-05-26 21:52:43 +02:00
Aliaksandr Kalenik
878cc16d7a LibJS: Use CallBuiltin for Math.cos() 2025-05-26 21:52:43 +02:00
Aliaksandr Kalenik
c02535e9f9 LibJS: Use CallBuiltin for Math.sin()
Improves performance on https://pierre.co/
2025-05-26 21:52:43 +02:00
Daniel Bertalan
04fac0031c AK: Add fast path for formatting common types
This commit changes `AK::TypeErasedParameter` to store integer,
floating-point and string types as well as characters and booleans
directly instead of through a type-erased `void const*`.

This is advantageous for binary size:
- The compiler no longer needs to push both the parameter value and a
  pointer to it to the stack (which contains the argument array);
  storing just the value is enough.
- Instead of instantiating `__format_value` for these types and taking
  its address (which generates a GOT entry and an ADRP+LDR pair in
  assembly), we just store a constant `TypeErasedParameter::Type` value.
- The biggest saving comes from the fact that we used to instantiate a
  distinct `__format_value` for each length of string literal. For
  LibJS, this meant 69 different functions! We can now just store them
  as a `char const*`.

I opted to use a manual tagged union instead of `Variant`: the code
wouldn't be much shorter if we used a `Variant` since we'd have to
handle converting the standard integer types to `u64`/`i64` and custom
types to the type erased wrapper via explicit constructors anyway. And
compile time overhead is smaller this way.

This gives us some nice binary size savings (numbers are from arm64
macOS LibJS):

     FILE SIZE        VM SIZE
  --------------  --------------
    +52% +10.3Ki   +52% +10.3Ki    [__TEXT]
   +5.2%    +768  +5.2%    +768    [__DATA_CONST]
   -0.0%      -7  -0.0%      -7    __TEXT,__cstring
   -3.0%    -144  -3.0%    -144    __TEXT,__stubs
   -1.2%    -176  -1.2%    -176    Function Start Addresses
  -11.6%    -432 -11.6%    -432    Indirect Symbol Table
   -1.0%    -448  -1.0%    -448    Code Signature
  -18.1%    -768 -18.1%    -768    __DATA_CONST,__got
   -0.8% -6.83Ki  -0.8% -6.83Ki    Symbol Table
   -1.0% -11.2Ki  -1.0% -11.2Ki    String Table
   -0.9% -26.1Ki  -0.9% -26.1Ki    __TEXT,__text
   -7.2% -20.9Ki  -9.6% -28.9Ki    [__LINKEDIT]
   -1.0% -56.0Ki  -1.1% -64.0Ki    TOTAL
2025-05-26 13:02:39 -06:00
Daniel Bertalan
9aaa4fd022 AK: Remove the formatter for unsigned char[N]
This is not used anywhere and its semantics are questionable.
2025-05-26 13:02:39 -06:00
blukai
3ab50be36a LibGfx: Improve logical separation of font_directories' ifdefs
in addition to what was proposed in
https://github.com/LadybirdBrowser/ladybird/pull/4830#discussion_r2101301978
2025-05-26 12:14:29 -06:00
blukai
e356a4bd01 LibGfx: Rely on fontconfig(if enabled) for font directory resolution
this commit also introduces GlobalFontConfig class that is now
responsible for fontconfig initialization. it seems sane, even thought
FcInit's docs state that if the default configuration has already been
loaded, this routine does nothing.
2025-05-26 12:14:29 -06:00
blukai
4b3691ff39 LibCore+LibGfx: Move font_directories from LibCore to LibGfx
the goal is to rely on fontconfig for font directory resolution. it
doesn't seem like it would be appropritate to call to fontconfig funcs
from within the LibCore.

i'm not 100% confident that FontDatabase is the correct place.. seems
okay?
2025-05-26 12:14:29 -06:00
blukai
6e00a38099 LibGfx: Enable otf fonts 2025-05-26 12:14:29 -06:00
Andreas Kling
ce33376b56 LibWeb: Make SVGGradientPaintStyle be atomically ref-counted
This was the only remaining data type used in display lists that wasn't
atomically ref-counted.

Now that it is, we no longer crash when scrolling on https://vercel.com/
2025-05-26 19:46:05 +02:00
Manuel Zahariev
addff9e35d LibJS: Unit tests for non-standard date formats 2025-05-26 18:48:09 +02:00
Manuel Zahariev
973110c046 LibJS: Convert date_parse_string to use DateParser 2025-05-26 18:48:09 +02:00
Manuel Zahariev
8263e7fa51 LibJS: DateParser for simplified ISO8601 and non-standard date strings 2025-05-26 18:48:09 +02:00
Manuel Zahariev
666c323577 AK/Error: Add value_or convenience method
- In the style of Optional::value_or
- Only const& flavor
- WARNING: no unit test (no unit tests for Error), but seems benign
2025-05-26 18:48:09 +02:00
Jelle Raaijmakers
47e1aa054b CI: Use explicit run IDs to download JS binary and call webhook
When we try to retrieve benchmark results in the webhook call, we cannot
use the `head_sha` parameter since the workflow run might have a
different `head_sha` associated with it than the upstream workflow run.
This can happen when the JS repl binary workflow runs, a new commit is
pushed to master, followed by a JS benchmarks workflow run causing this
latter run to be associated with a different commit ID.

This extends the webhook payload to include the current run ID, which
can eventually be used by the webhook script to specifically download
the benchmark results associated with the current run.

Additionally, this changes the JS artifact download to use the upstream
run ID which seems nicer to do anyway.
2025-05-26 17:18:40 +02:00
Luke Wilde
89762e2ff3 LibWeb/WebGL: Free back buffer texture when context is destroyed 2025-05-26 17:16:42 +03:00
Luke Wilde
38713d7c14 LibWeb/WebGL: Return vertex shader from Program::attached_vertex_shader 2025-05-26 17:16:42 +03:00
Aliaksandr Kalenik
dcfc515cd0 LibJS: Fix arrow function parsing bug
In the following example:
```js
const f = (i) => ({
    obj: { a: { x: i }, b: { x: i } },
    g: () => {},
});
```

The body of function `f` is initially parsed as an arrow function. As a
result, what is actually an object expression is interpreted as a formal
parameter with a binding pattern. Since duplicate identifiers are not
allowed in this context (`i` in the example), the parser generates an
error, causing the entire script to fail parsing.

This change ignores the "Duplicate parameter names in bindings" error
during arrow function parameter parsing, allowing the parser to continue
and recognize the object expression of the outer arrow function with an
implicit return.

Fixes error on https://chat.openai.com/
2025-05-26 12:44:21 +03:00
Chris Mulder
09463f147d LibWeb: Do not clear the selection, when query is not found
Fixes #4743
2025-05-26 11:22:48 +02:00
Timothy Flynn
ad4634d0ed LibMedia: Use a simple locked vector to handle audio commands on macOS
The SharedSingleProducerCircularQueue used here has dubious value, This
queue is used to pass commands to the audio thread, such as play/pause/
seek/volume change/etc. We can make do with a simple locked vector, as
we were blocking to enqueue tasks anyways. We can also use an atomic
bool to tell the audio thread when it needs to take a lock on the task
queue, to keep the thread lock-free most of the time.
2025-05-25 08:45:50 -04:00
Shannon Booth
172556db74 LibWeb/HTML: Don't log FIXME messages for location.ancestorOrigins
This is quite a frequent FIXME log on quite a few sites which
does not serve much value at this stage. So instead of marking it
with a FIXME extended IDL attribute, let's just comment it out.
2025-05-25 08:45:30 -04:00
Andrew Kaster
8095663f86 LibIPC: Chunk sent file descriptors by MAX_TRANSFER_FDS
This limitation of the underlying Unix socket implementation can
cause IPC failures on pages with tons of images and network requests.

Modify the code called from TransportSocket's send thread to limit the
number of fds to MAX_TRANSFER_FDS, and ensure that we will keep sending
as long as we have either bytes or file descriptors to send.
2025-05-24 19:15:06 +03:00
Andrew Kaster
87fbfcadd1 LibIPC: Refactor message header encoding to use a helper method
Manually memcpying into a Vector in the body of post_message is
a bit much.
2025-05-24 19:15:06 +03:00
Andrew Kaster
087cbf2b0a LibCore: Expose Unix socket fd transfer limit publicly 2025-05-24 19:15:06 +03:00
Shannon Booth
8ccb89877a LibWeb/HTML: Return an opaque origin for data URLs for Workers 2025-05-24 09:51:44 -04:00
Shannon Booth
9aabe88795 WebWorker: Ensure global object has URL set before fetching
As explained by the comment in the code. I believe this to be a
spec issue, which I will report.
2025-05-24 09:51:44 -04:00
Shannon Booth
40d21e343f LibURL: Add FIXME's for testing equality of opaque origins
The spec seems to indicate in its wording that while opaque
origins only serialize to 'null', they can still be tested
for equality with one another. Probably we will need to
generate some unique ID which is unique across processes.
2025-05-24 09:51:44 -04:00
Aliaksandr Kalenik
ceaeea3c26 RequestServer: Use write notifier instead of busy waiting for socket
...to become writable.

Solves triangular deadlock problem that happened in the following case
(copied from https://github.com/LadybirdBrowser/ladybird/issues/1816):
- The WebContent process is spinning on
   `send_sync_but_allow_failure` waiting for the UI process to respond
- The UI process is spinning on `send_sync_but_allow_failure`, waiting
   for RequestServer to respond
- RequestServer is stuck in this loop, trying to write to the
  WebContent's socket file (when I attach to RS, we are always in the
  sched_yield call, so we're spinning on EAGAIN).

For me the issue was reliably reproducible on Google Maps and with this
change we no longer deadlock there.
2025-05-24 16:28:48 +03:00
Timothy Flynn
522d13b0fb Revert "Meta: Update skia to version 134"
This reverts commit 51d189198d.

This neglected to update the overlay port, thus had no effect.
2025-05-24 06:55:15 -06:00
Andrew Kaster
228211205a LibCore: Atomically ref-count SharedSingleProducerCircularQueue guts
This fixes two race conditions and ASAN crashes in the test for the
same.

The first comes from destroying the internals struct, which was
previously using the standard, thread-unsafe RefCounted CRTP. The
second is from destroying the name, which is secretly another
RefCounted object, in a thread-unsafe manner.
2025-05-24 06:52:25 -06:00
Sam Atkins
f5cd853597 LibWeb/CSS: Avoid calling to_font_weight() when serializing font
This function attempts to resolve `lighter` and `bolder`, which we don't
want to do when serializing - that should happen in style computation.

This has the unexpected bonus of 37 more WPT passes!
2025-05-24 13:35:30 +01:00
Gingeh
3fe148f2d4 LibWeb: Implement the :default pseudo-class 2025-05-24 10:31:34 +01:00
Gingeh
7acc0f4a42 LibWeb: Implement :required/:optional pseudo-classes 2025-05-24 10:31:34 +01:00
Timothy Flynn
fbd1f77161 LibWeb: Disentangle both ends of a MessagePort at once
Otherwise, the remote end believes it is still entangled and may try to
access its own (now null) remote port. This fixes a crash in WPT.
2025-05-24 10:47:06 +12:00
Sam Atkins
ea44a1c2c7 LibWeb/CSS: Don't treat "-foo" as vendor-prefixed
To be vendor-prefixed, an ident has to start with a '-', then have
another '-' later. If the ident simply starts with a '-' then that's
perfectly fine.

Fixes 62 in-tree WPT subtests. :^)
2025-05-23 19:39:23 +01:00
Sam Atkins
f5825ab18c LibWeb/CSS: Stop erasing font-variant-css2 value in font shorthand
We don't want to reset the values of `font-variant-*` here, as that will
override whatever our parsed font-variant-css2 was, so stop doing that.

Also, font-stretch is mentioned in the spec, but it's a legacy name
alias for font-width, so we don't need to do anything for it.

Gets us 319 WPT passes!
2025-05-23 19:39:23 +01:00
Sam Atkins
d9a8349d8c LibWeb/CSS: Parse font-variant and font-weight parts of font properly
These are not the same as parsing their properties, but are limited to a
small set of keywords each. The easiest way to handle these is parsing
them directly here.

Update some comments while I'm here.
2025-05-23 19:39:23 +01:00
Sam Atkins
8c78925dd3 LibWeb/CSS: When dumping CSS tokens, point at the next one
The meaning of m_index changed a while back and this never got updated.
Pointing at the value that was last consumed is confusing.
2025-05-23 19:39:23 +01:00
Timothy Flynn
fc54b9db46 Meta: Update sqlite3 to version 3.49.2 2025-05-23 18:10:51 +02:00
Timothy Flynn
51d189198d Meta: Update skia to version 134 2025-05-23 18:10:51 +02:00
Timothy Flynn
36040d1580 Meta: Update openssl to version 3.5.0 2025-05-23 18:10:51 +02:00
Timothy Flynn
152858fe7c Meta: Update libwebp to version 1.5.0 2025-05-23 18:10:51 +02:00
Timothy Flynn
40d3f925ba Meta: Update libavif to version 1.3.0 2025-05-23 18:10:51 +02:00
Timothy Flynn
b9cbd3436c Meta: Update libpng to version 1.6.47 2025-05-23 18:10:51 +02:00
Timothy Flynn
8232ae2bf3 Meta: Update fontconfig to version 2.15.0 2025-05-23 18:10:51 +02:00
Timothy Flynn
cb7dacc56a Meta: Update ffmpeg to version 7.1.1 2025-05-23 18:10:51 +02:00
Timothy Flynn
726ed55c3f Meta: Update vcpkg baseline 2025-05-23 18:10:51 +02:00
Shannon Booth
cdb249e058 LibWeb/HTML: Set a fetch client for javascript URL navigations
There is an open spec issue for this, and I'm certainly not sure
what the client should be here, but using the source snapshot
from the global from reading the spec issue seems like a reasonable
enough client for now.

This can be reproduced by performing a javascript URL navigation
with any CSP policy set. For simplicity, simply edit an existing
testcase to add such a policy.

Fixes: #4853
2025-05-23 16:39:13 +02:00
Luke Wilde
e364443e60 LibWeb: Support Content-Security-Policy http-equiv state on meta element 2025-05-23 16:39:13 +02:00
Andreas Kling
59e2416b61 LibWeb: Handle format(woff-variations) etc in @font-face src values
"format(woff-variations)" and pals are supposed to expand like so:
"format(woff) tech(variations)".

However, since we don't support tech() yet, this patch just adds a small
hack where we still treat "woff-variations" as "woff" so that fonts
load and get used, even if we don't make use of the variations yet.
2025-05-23 16:36:56 +02:00
Andreas Kling
2d064116ab Tests: Import a WPT test for @font-face format specifiers 2025-05-23 16:36:56 +02:00
Callum Law
9dfce6d14c Meta: Avoid doublequote strings nested in fstrings in ladybird.py
Double quote strings nested within double quoted-fstrings are invalid
syntax prior to Python 3.12 and was causing an error when running
ladybird.py
2025-05-23 10:27:34 -04:00
Aliaksandr Kalenik
bd6750aaa5 LibJS: Skip prototype chain lookup in internal_set() for arrays
...when Array.prototype and Object.prototype are intact.

If `internal_set()` is called on an array exotic object with a numeric
PropertyKey, and:
- the prototype chain has not been modified (i.e., there are no getters
  or setters for indexed properties), and
- the array is not the target of a Proxy object,

then we can directly store the value in the receiver's indexed
properties, without checking whether it already exists somewhere in the
prototype chain.

1.7x improvement on the following program:
```js
function f() {
    let a = [];
    let i = 0;
    while (i < 10_000_000) {
        a.push(i);
        i++;
    }
}

f();
```
2025-05-23 14:51:32 +02:00
Aliaksandr Kalenik
6404f6db57 LibJS: Delete unused Shape::create_for_prototype() 2025-05-23 14:51:32 +02:00
Callum Law
279913a223 LibWeb: Implement the translate attribute 2025-05-23 14:34:06 +02:00
devgianlu
4b3715ccba LibCrypto: Replace {Unsigned,Signed}BigInteger impl with LibTomMath
Replace the implementation of maths in `UnsignedBigInteger`
and `SignedBigInteger` with LibTomMath. This gives benefits in terms of
less code to maintain, correctness and speed.

These changes also remove now-unsued methods and improve the error
propagation for functions allocating lots of memory. Additionally, the
new implementation is always trimmed and won't have dangling zeros when
exporting it.
2025-05-23 11:57:21 +02:00
devgianlu
915c6fdcf8 LibCrypto: Add libtommath vcpkg dependency and link it
An overlay port is required to add the `stdc-iec-559` and `install-pc`
patches.

The `stdc-iec-559` patch is required because Clang doesn't define
`__STDC_IEC_559__`. However, glibc and musl define it if `__GCC_IEC_559`
is not defined. The macro is taken from glibc source code.

The `install-pc` patch is required because libtommath doesn't install
the pkg-config files when building statically compromising our ability
to find it during build.

Clang: https://clang.llvm.org/c_status.html#:~:text=Yes-,
IEC%2060559%20support,-Unknown
glibc: https://sourceware.org/git/?p=glibc.git;a=blob;
f=include/stdc-predef.h
2025-05-23 11:57:21 +02:00
devgianlu
5a4cfd05d0 LibCrypto+LibJS: Move Power to method of {Unsigned,Signed}BigInteger
Having it as a method instead of a free function is necessary for the
next commits and generally allows for optimizations that require deeper
access into the `UnsignedBigInteger` / `SignedBigInteger`.

Also restrict the exponent to 32 bits to avoid huge memory allocations.
2025-05-23 11:57:21 +02:00
devgianlu
a952d000be LibCrypto: Move GCD to method of UnsignedBigInteger
Having it as a method instead of a free function is necessary for the
next commits and generally allows for optimizations that require deeper
access into the `UnsignedBigInteger`.
2025-05-23 11:57:21 +02:00
Sam Atkins
e251b451ef LibWeb/CSS: Reject negative <resolution> values
Gets us 3 more WPT passes.
2025-05-23 10:17:58 +01:00
Sam Atkins
fb975cc156 LibWeb/CSS: Correct how we evaluate boolean media-features
The spec has a general rule for this, which is roughly that "If it's not
a falsey value, it's true". However, a couple of media-features are
always false, apparently breaking this rule. To handle that, we have an
array of false keywords in the JSON, instead of a single keyword. For
those always-false media-features, we can enter all their values into
this array.

Gets us 2 more WPT subtest passes.
2025-05-23 10:17:58 +01:00
Sam Atkins
00617884a6 LibWeb/CSS: Correct our scan media-feature
Despite what the spec suggests, modern displays are not progressive, and
WPT expects `@media (scan: progressive)` to fail. So, return `none`
here to accurately represent that.

I've left a FIXME in case we can detect the display type from the OS
somehow in the future.

Gets us 4 WPT subtest passes.
2025-05-23 10:17:58 +01:00
Sam Atkins
9fe8445946 LibWeb/CSS: Maintain original form of media-feature ranges
Previously, for `foo < 30px` ranges, we'd flip them and store them as
`30px > foo` instead. That worked fine, but means the serialization is
wrong. So instead, keep them in their original form.

I experimented with giving Range two optional sub-structs instead of 4
optional members, thinking it would be smaller - but it's actually
larger, because the two Optional<Comparison>s fit snugly together. So,
the slightly-goofy all-Optionals remains.

This gets us 2 WPT passes that I'm aware of.
2025-05-23 10:17:58 +01:00
Sam Atkins
9b8dc6b8d0 LibWeb/CSS: Parse media-feature values forgivingly
Instead of rejecting invalid media-feature values at parse time, we are
expected to parse them, and then treat them as Unknown when evaluating
their media query. To implement this, we first try to parse a valid
value as before. If that fails, or we have any trailing tokens that
could be part of a value, we then scoop up all the possible
ComponentValues and treat that as an "unknown"-type MediaFeatureValue.

This gets us 66 WPT passes.
2025-05-23 10:17:58 +01:00
Sam Atkins
72f50217b0 LibWeb/CSS: Implement device-aspect-ratio media feature
Gets us 8 WPT passes, and prevents a regression in the following commit.
2025-05-23 10:17:58 +01:00
Sam Atkins
b577302f07 LibWeb/CSS: Make media type and feature evaluation combination explicit
Functionally this is the same before, as result is always True or False
before this point, and `True && Foo` evaluates to `Foo`. But this is
more clearly correct, instead of correct by coincidence.
2025-05-23 10:17:58 +01:00
Sam Atkins
a4d3c62524 LibWeb/CSS: Return a MatchResult from MediaFeature::compare()
This commit on its own has no observable behaviour changes, as we still
only return True or False, but for the next commit, we'll need to be
able to return the Unknown state here, and without this change we'd get
regressions.
2025-05-23 10:17:58 +01:00
Sam Atkins
fe7bac73f0 LibWeb/CSS: Stub out a function for serializing ComponentValue sequences
This is very hacky and wrong, but it means there's one place to fix,
instead of one for UnresolvedStyleValue, and one for invalid
MediaFeatureValues which I'm about to implement.
2025-05-23 10:17:58 +01:00
Sam Atkins
987d510dbb LibWeb/CSS: Allow "picture-in-picture" in "display-mode" media feature
We don't implement detection for this yet, but it gets us a WPT pass.
2025-05-23 10:17:58 +01:00
Sam Atkins
38aca62ef5 LibWeb/CSS: Make media-type more permissive
The current spec defines this simply as `<ident>`, but does apparently
serialize as lowercase.

Because of this change, we no longer need to care about the deprecated
media types, as they all behave the same as unknown ones.

We still keep an enum around for KnownMediaType, to avoid repeated
string comparisons when evaluating it.

Gets us 2 WPT passes.
2025-05-23 10:17:58 +01:00
Sam Atkins
bb035fbfe0 Tests: Import a whole bunch of WPT mediaqueries tests
A lot of these are ref-tests, so I'm skipping the failing ones for now,
and will make as many pass as possible in subsequent commits.
2025-05-23 10:17:58 +01:00
Aziz Berkay Yesilyurt
6711438e0d LibWeb: Ensure anonymous wrappers inherit inline-block display
When restructuring a block node inside an inline parent, if the
nearest block ancestor is `display: inline-block`, ensure that
the generated anonymous wrappers also have `display: inline-block`.
This fixes layout issues with block elements nested
inside inline-block elements.
2025-05-23 11:16:06 +02:00
Ruben
09f5ce42f6 LibWeb: Ensure floats are correctly placed under the preceding float
Previously floats would be placed next to the highest float that
fitted the new float on its line. However, this violates the rule
that floats should be placed under the preceding float if it does
not fit next to it.
2025-05-23 10:58:15 +02:00
Shannon Booth
3bf7f94150 LibJS: Use caller_context to determine strict mode
This is functionaly the same since caller_context is the topmost
execution context on the stack, but makes it more clear that
we are directly inheriting the strict mode from the caller context
when pushing the next context on to the stack.
2025-05-23 03:25:55 +02:00
Shannon Booth
7d44640c0f LibJS: Assume is_strict_mode called with running execution context
This should always be invoked when there is an execution context
on the stack.
2025-05-23 03:25:55 +02:00
Shannon Booth
f2fb86abea LibJS: Always emit value in emit_named_evaluation_if_anonymous_function
There does not appear to be any case that we need to return an
OptionalNone{}.
2025-05-23 03:25:55 +02:00
Shannon Booth
20dba8f1ab LibJS: Make Op::Return value required
It turns out we do not have any scenario where this is not provided.
2025-05-23 03:25:55 +02:00
Timothy Flynn
17364c6d36 Tests: Disable XMLHttpRequest-override-mimetype-blob.html for now
It is extremely slow on macOS.
2025-05-22 18:40:25 -04:00
ayeteadoe
fdd3f35b61 Meta: Localize resource module import to fix ladybird.py on Windows 2025-05-22 17:48:03 -04:00
Timothy Flynn
4c8b5ba9de Tests/LibWeb: Add a screenshot test for acid2
This test has flaked over the years, so let's add a screenshot test to
catch future regressions.

This copy of the test was taken from:
https://www.webstandards.org/files/acid2/test.html#top

Our CI infra does not support navigating to the "#top" anchor out of the
gate. So the intro section was removed from this copy so that we render
the happy face immediately.
2025-05-22 17:44:40 -04:00
Timothy Flynn
8b787020a2 LibWeb: Delay the document load event while re-fetching <object> images
We are required to delay the load event while any fetch is ongoing. We
currently have a very hacky re-fetch for images to go through the shared
resource request infrastructure. We must delay the load event during
this re-fetch.

This becomes an issue in an upcoming commit to import the acid2 test.
2025-05-22 17:44:40 -04:00
Timothy Flynn
1bc7a52587 LibWeb: Keep delaying the load event on concurrent <object> tasks
If we queue the <object> representation task multiple times in a row, we
would end up clearing the delayer after the first task completed. We
must continue delaying the load event until the last task completes.

This becomes an issue in an upcoming commit to import the acid2 test.
2025-05-22 17:44:40 -04:00
Timothy Flynn
874e094ed8 LibWeb: Allow moving document load event delayers
This allows us to store lists of delayers.
2025-05-22 17:44:40 -04:00
Lion Kortlepel
900500c0b3 LibWeb: Remove obsolete font-style Keyword handling
`Parser::parse_font_style_value()` only produces
FontStyleStyleValues now, so we no longer need this
branch.
2025-05-22 17:39:05 +01:00
Lion Kortlepel
b1ee539e9d LibWeb: Fix font-style to slope conversion
In a recent refactor of font styles, the new FontStyleStyleValue was
introduced; however, the `to_font_slope()` function was not changed to
understand this new type. When it tries to convert such a font style to
a keyword, it fails. We then rendered the wrong font-style.
2025-05-22 17:39:05 +01:00
Timothy Flynn
d00d49ba2f Meta+Toolchain: Extract BuildVcpkg to an importable function
This lets ladybird.py import it properly, instead of invoking BuildVcpkg
main().
2025-05-22 12:21:24 -04:00
Timothy Flynn
8d4ac42205 Meta: Always invoke BuildVcpkg from ladybird.py's build command
We were previously only invoking it if the Build directory didn't exist.
We need to always invoke it to handle vcpkg baseline updates.
2025-05-22 12:21:24 -04:00
Callum Law
64f09b520d LibWeb: Be less aggressive in marking elements as not being named
When an element's ID is removed we only want to remove it from
`m_potentially_named_elements` if it is not also considered a
potentially named element due to it's name content attribute.
2025-05-22 16:56:02 +02:00
Timothy Flynn
2f9957c618 Everywhere: Format all python files with black 2025-05-22 16:21:42 +02:00
Timothy Flynn
9e8336c04f Meta: Lint python files with black
It's the industry standard nowadays. This also lets us add a flag to the
lint-python.sh script to overwrite our python files in place.
2025-05-22 16:21:42 +02:00
Tim Ledbetter
fe99c1fa7c LibCore: Increase MAX_LOCAL_SOCKET_TRANSFER_FDS
It is currently possible to hit this limit on pages with large numbers
of images. This temporary workaround prevents some WPT tests with large
numbers of images from failing.
2025-05-22 08:00:01 -04:00
Gingeh
71222df4c4 LibWeb: Update button activation behaviour to match spec
See: https://github.com/whatwg/html/pull/11248
See: https://github.com/whatwg/html/pull/11325
2025-05-22 07:55:34 +01:00
Gingeh
f1eaecc630 LibWeb: Escape "<" and ">" when serializing attribute values
See https://github.com/whatwg/html/pull/6362
2025-05-22 07:55:34 +01:00
Gingeh
fbc56f74bd LibWeb: Move popover invoker reset later
See https://github.com/whatwg/html/pull/11304
2025-05-22 07:55:34 +01:00
Ali Mohammad Pur
a3b913bf91 Tests: Import the call-indirect wpt wasm test
This found some broken wasm-js implementations, so let's make sure it
doesn't break again.
2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
83995ada1f LibWasm: Quit early in memory_fill if store_to_memory traps
We shouldn't try to run the next 'instruction' if we trap.
Unbreaks the memory-fill test in wpt.
2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
bfc1ebb2d4 LibWasm: Disable spammy 'memory access oob' debug prints 2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
d79d5b70a5 LibWasm: Validate indirect calls at runtime
This is required by the spec, and also unbreaks all of the call-indirect
wpt tests.
2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
39b637a446 LibWasm+LibWeb: Throw a js stack-overflow error if wasm stack overflows
Follows the spec.
2025-05-22 07:35:58 +01:00
Timothy Flynn
9ae85e5c68 Meta: Avoid manual formation of user-variables.cmake path
We're using python specifically to be platform-independent.
2025-05-21 16:55:27 -06:00
Timothy Flynn
5b830b4c05 Meta: Be a bit less aggressive with newlines in list extensions 2025-05-21 16:55:27 -06:00
Timothy Flynn
bac61926b2 Meta: Use fewer abbreviated variable names in ladybird.py 2025-05-21 16:55:27 -06:00
Timothy Flynn
b54f273770 Meta: Ignore pyright warning for dynamic BuildVcpkg import
There are now zero pyright warnings.
2025-05-21 16:55:27 -06:00
Timothy Flynn
6a1b3f740c Meta: Avoid double-access of LADYBIRD_SOURCE_DIR environment variable
The `ensure_ladybird_source_dir` function returns the source directory.
Let's just use it. This silences a pyright warning.
2025-05-21 16:55:27 -06:00
Timothy Flynn
23a95cfb9a Meta: Add missing type hints to ladybird.py
This enables significantly better LSP integration.
2025-05-21 16:55:27 -06:00
Timothy Flynn
9d3d0c4874 Meta: Sprinkle some newlines into ladybird.py
Long functions without newlines between logical blocks of code get hard
to read for me after a while.
2025-05-21 16:55:27 -06:00
Timothy Flynn
6862985b08 Meta: Do not conflate build and run arguments
The previous commit preserved existing behavior from `master`, but made
it clear that the script was trying to use the `run` arguments in the
build step. We currently cannot specify both build-time and run-time
arguments, so only pass the positional arguments to the run step.
2025-05-21 16:55:27 -06:00
Timothy Flynn
620a2b7598 Meta: Do not pass arguments around as kwargs in ladybird.py
Use proper function arguments instead.
2025-05-21 16:55:27 -06:00
Timothy Flynn
16feb0b979 Meta: Move ladybird.py imports to the top of the file
There's no measurable benefit to hiding these in functions, even if they
are only used once (or not at all). Only the BuildVcpkg import is left
alone, as that function does some sys.path manipulation first.
2025-05-21 16:55:27 -06:00
Timothy Flynn
f87a90b67b Meta: Remove underscore prefix from functions in ladybird.py
These are meant to indicate private functions by convention, and while
we can argue these functions are "private" to this file, let's err on
the side of readablilty over every single function being prefixed.
2025-05-21 16:55:27 -06:00
Timothy Flynn
ec863a6d8b Meta: Format ladybird.py with black
We require pep8 conformance via flake8 in CI, and flake8 seems happy
with this patch. In the future, we should enforce use of black in CI
as well.

Formatted with:

    black --line-length 120 ./Meta/ladybird.py
2025-05-21 16:55:27 -06:00
Andrew Kaster
811d53d295 CI: Add nightly Windows CI job
This job uses the windows_ci_ninja preset to build just the
components and unit tests that are known to work with ClangCL on the
amd64-pc-windows-msvc target triple.

As a nightly job, its failures are non-blocking for any PRs, though
they should be fixed eventually or the job will get turned off by
email-annoyed maintainers.
2025-05-21 15:57:59 -06:00
Timothy Flynn
9f3526b080 LibWeb: Handle non-OK network responses in <object> elements
We were previously only testing for network errors, which includes e.g.
DNS resolution and connection errors. It does not include e.g. HTTP 404
responses, which is exercised by Acid 2.
2025-05-21 12:13:20 -06:00
Ashton
fc204c8732 Meta: Add addr2line command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
061a7f766c Meta: Add rebuild command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
56fd109252 Meta: Add clean command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
bfc0715455 Meta: Add vcpkg command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
08d11b9fba Meta: Add debug command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
5602d3cdf1 Meta: Add install command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
73159fe2ce Meta: Add run command to ladybird.py 2025-05-21 11:35:20 -06:00
Ashton
c51abfb2ca Meta: Add test command to ladybird.py 2025-05-21 11:35:20 -06:00
ayeteadoe
c9624d5118 Meta: Add build command to ladybird.py 2025-05-21 11:35:20 -06:00
Noah
85842c1739 LibWeb: Stub out several methods for ElementInternals
This begins implementation on form-associated custom elements.
This fixes a few WPT tests which I'm importing.

Co-authored-by: Sam Atkins <sam@ladybird.org>
2025-05-21 15:28:10 +01:00
Veeti Paananen
7c4fd9f624 LibWeb/CSS: Use case insensitive tag and attribute name in ancestor hash
Fixes #4793.
2025-05-21 08:54:40 -04:00
Shannon Booth
579730d861 LibWeb: Prefer using equals_ignoring_ascii_case
Which has an optmization if both size of the string being passed
through are FlyStrings, which actually ends up being the case
in some places during selector matching comparing attribute names.
Instead of maintaining more overloads of
Infra::is_ascii_case_insensitive_match, switch
everything over to equals_ignoring_ascii_case instead.
2025-05-21 13:45:02 +01:00
Ali Mohammad Pur
cfc241f61d LibRegex: Make the trie rewrite optimisation maintain the alt order
This is required by the spec.
2025-05-21 14:28:45 +02:00
Ali Mohammad Pur
2eccd68ba5 LibRegex: Document the append_alternative optimisation a bit 2025-05-21 14:28:45 +02:00
Timothy Flynn
95fc0a8070 LibWeb: Implement TransformStream transfer 2025-05-21 06:54:44 -04:00
Timothy Flynn
cca08ad833 LibWeb: Implement WritableStream transfer 2025-05-21 06:54:44 -04:00
Timothy Flynn
312db85a84 LibWeb: Implement ReadableStream transfer 2025-05-21 06:54:44 -04:00
Timothy Flynn
7e225b496d LibWeb: Implement transferable streams AOs
These AOs are common between transferable ReadableStream, WritableStream
and TransformStream objects.
2025-05-21 06:54:44 -04:00
Timothy Flynn
ee9d860ba2 LibWeb: Allow creating a MessagePort with a different primary interface
This is needed to transfer streams, which use message ports as the means
of transport.
2025-05-21 06:54:44 -04:00
Timothy Flynn
36da270dbe LibIPC+LibWeb: Flush MessagePort messages before closing
The spec isn't super clear on what disentagling a MessagePort means. But
we are required to send all pending messages before closing the port.

This is a bit tricky because the transport socket performs writes on a
background thread. From the main thread, where the disentanglement will
occur, we don't really know the state of the write thread. So what we do
here is stop the background thread then flush all remaining data from
the main thread.
2025-05-21 06:54:44 -04:00
Timothy Flynn
8b3355ed0d LibIPC: Address a couple of clangd warnings in IPC::TransportSocket
* We need the full definition of IPC::File in the header.
* We need(ed) Core::System in the header. Move AutoCloseFileDescriptor's
  ctor and dtor out-of-line to avoid this.
2025-05-21 06:54:44 -04:00
Timothy Flynn
356727f294 LibWeb: Provide missing includes to StructuredSerializeTypes.h 2025-05-21 06:54:44 -04:00
Aliaksandr Kalenik
95e1ec4abc LibJS: Skip caching get_by_id() if object's shape is changed by a getter
Fixes a bug that reproduces with the following steps:
1. Create an object with a getter for property "a" in its prototype,
   where the getter adds an "a" property to the object itself.
2. Call the "a" getter in a loop for the first time. This triggers
   caching of metadata indicating that the "a" property is located in
   the prototype chain.
3. Call the "a" getter in a loop for the second time. Oops, the cache
   says the getter is in the prototype chain, but the object now
   also has its own "a" property that was added by the first getter
   call.
2025-05-20 19:10:56 -04:00
Ahmed Elawad
7af188dc52 Documentation: Fix Ladybird's documentation url 2025-05-20 15:53:48 -04:00
Andrew Kaster
0c434485b4 CMake: Rework Windows build and test presets
Make them work with the new preset names, and hide platform-specific
presets on platforms that don't support them.
2025-05-20 12:51:30 -06:00
ayeteadoe
8cf01a25c2 AK: Add initial support for AK testsuite on Windows
We now explicitly enabling support for the minimum libraries needed
to build and run the AK testsuite. 81/82 tests are running and
passing. The exception is LexicalPath, as some path behaviour on
Windows is different than Unix, so the current tests will have lots of
platform specific failures. The implementer of LexicalPathWindows
recommended windows-specific tests here, so I will do that in a
follow up.
2025-05-20 10:58:43 -06:00
ayeteadoe
a11242f3de CMake: Expose Windows CI utilities
This will allow us to gradually build up official support for Windows,
as only targets we have explicitly marked as supported on windows will
be built and ran during CI.
2025-05-20 10:58:43 -06:00
Timothy Flynn
d26b8b2537 Documentation: Show how to generate reference screenshots for tests 2025-05-20 10:48:03 -04:00
Timothy Flynn
344d6efd11 Documentation: Update notes about LibWeb test paths
All test types have `input` and `expected` folders.
2025-05-20 10:48:03 -04:00
Timothy Flynn
1933d5fa44 Documentation: Remove non-ASCII characters from Testing.md
Removes some NBSP and non-ASCII quotes/hyphens in favor of keeping this
document simpler to manage.
2025-05-20 10:48:03 -04:00
Timothy Flynn
141afbc63d headless-browser: Allow specifying the path to the saved screenshot
This is to help make creating Screenshot tests a bit easier.
2025-05-20 10:48:03 -04:00
Andreas Kling
d7cd8f0fc7 LibWeb: Make CSS sign(A) ignore A's unit and just look at the raw value
This allows stuff like sign(1em) even when we don't have something to
resolve the em unit against.

+25 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
4ef34ebd96 LibWeb: Make CSS sign(A) behave correctly for negative zero
We were incorrectly returning 0 instead of -0 for sign(-0).

+7 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
c1e79d0b13 LibWeb: Handle calc() in CSS z-index
We also make getComputedStyle() reflect the actually used z-index value,
since otherwise this change is hard to observe.

+26 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
821d54de7f LibWeb: Invalidate layout tree on CSS position property change
When position changes, we may need to make larger structural updates
to the layout tree. A simple relayout is not sufficient.

This was a source of flakiness in the engine, and gives us at least
+28 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andrew Kaster
f66c55138b Utilities: Move install rules for js repl to Utilities 2025-05-19 18:37:15 -04:00
Andrew Kaster
6548f9b6dd CMake: Move library subdirectory inclusion to Libraries/CMakeLists.txt 2025-05-19 18:37:15 -04:00
Andrew Kaster
e4fb3a86a1 Tests: Move Tests CMake rules to Tests/CMakeLists.txt
Get this logic out of Meta/Lagom/CMakeLists.txt, in the hope that we
can eventually remove the Lagom CMakeLists.txt file entirely.
2025-05-19 18:37:15 -04:00
Andrew Kaster
26c76a8347 Tests: Move test-wasm build rules to Tests/LibWasm 2025-05-19 18:37:15 -04:00
Andrew Kaster
da106177b4 AK: Move install rules into AK's CMakeLists 2025-05-19 18:37:15 -04:00
Andrew Kaster
5418165690 Tests: Move LibJS test rules to Tests/LibJS 2025-05-19 18:37:15 -04:00
Andrew Kaster
72ca813b6b CMake: Handle CMP0174 in Lagom CMake functions, and support CUSTOM_MAIN 2025-05-19 18:37:15 -04:00
Andrew Kaster
bf01470732 Tests: Remove unused test-test262 application
This test app was created to run test262-based tests on the SerenityOS
target, without having to port the entire test262 runner and driver
python script. We have no need for it here.
2025-05-19 18:37:15 -04:00
Andrew Kaster
432bc0f638 LibTLS+Tests: Build LibTLS tests from their test directory
Instead of building them from Lagom, build them here and use lagom_test.
Also remove second download of cacert.pem.
2025-05-19 18:37:15 -04:00
Andrew Kaster
1878ed10d2 CMake: Move Utilities build rules to Utilities directory 2025-05-19 18:37:15 -04:00
Andrew Kaster
94a20f6706 Tests+Utilities: Move test262-runner to Utilities
This is a utility more than it is a test in itself. We use it to run
test262 tests, which are external to this repo. The test-js runner is
still private test infrastructure though, so it stays where it is.
2025-05-19 18:37:15 -04:00
Andrew Kaster
52efd90445 CMake: Remove old gcc version check
We require newer than gcc 12 at this point, so this check is no longer
needed.
2025-05-19 18:37:15 -04:00
Sam Atkins
6e45d8ba6c LibWeb/CSS: Set enum sizes for PropertyID and Keyword
The effect of this is hard to measure, but reducing them from 4 bytes
each to 2 bytes can't hurt. :^)
2025-05-20 10:14:21 +12:00
Sam Atkins
3add623f22 LibWeb/CSS: Use underlying_type_for_enum() for Enums.json generator
Replacing the duplicate implementation.
2025-05-20 10:14:21 +12:00
Sam Atkins
c4bcbff59a LibWeb/CSS: Set enum sizes for media query types
This reduces `MediaFeature` from 112 to 104 bytes.
2025-05-20 10:14:21 +12:00
rmg-x
e2fa8cf7a8 LibWeb+Tests: Continue variable expansion if CSS-wide keyword is parsed
This allows the existing fallback logic in `Parser::expand_variables` to
run when a CSS-wide keyword is encountered.
2025-05-19 16:32:07 +01:00
Andreas Kling
ab051f2e12 LibWeb: Maintain tree order inside LayoutState
Before this change, we were at the mercy of hashed pointer addresses
when processing fragment relocation in LayoutState::commit().
This made inline fragment order non-deterministic, causing layouts to
shift around seemingly randomly on page reload.

By simply using OrderedHashMap, we automatically get tree order
processing here. This fixes a bunch of flaky tests on WPT.
2025-05-19 15:21:53 +02:00
Tim Ledbetter
5dc507c573 Tests: Re-enable some ref tests that now pass 2025-05-19 14:12:25 +01:00
Tim Ledbetter
2f71f563c6 Tests: Re-enable HTML parsing tests that previously crashed 2025-05-19 14:12:25 +01:00
Andreas Kling
1a055fcb24 LibWeb: Mark canvas element for relayout when width or height changes
While width and height are presentational hints on canvas, they actually
map to the CSS aspect-ratio attribute, not to CSS width and height.
For this reason, we actually need to manually mark for relayout here.

Also import a WPT test that was flaky before this change.
2025-05-19 13:58:05 +02:00
Shannon Booth
14d5c638eb LibWeb/HTML: Use find flattened slots in assignedElements/assignedNodes
This is very awkward, and should be improved, but this improves
our support for slots :^)
2025-05-19 23:26:02 +12:00
Shannon Booth
2d6b11c8cb LibWeb/DOM: Implement 'find flattened slottables'
Returning a Vector of Slottable is not very nice here, but this
matches find_slottable (which this calls), and as far as I can
tell this is technically 'safe' at the moment in the way in
which it is / will be called.

It's also not great that like find_slottable it takes a non-const
ref, but changing that causes a bunch of other fallout.
2025-05-19 23:26:02 +12:00
Shannon Booth
98c45f3f03 Tests/LibWeb: Import a bunch of slots WPT tests 2025-05-19 23:26:02 +12:00
Colin Reeder
5ac88e7726 RequestServer: Leave Accept-Encoding up to curl 2025-05-19 13:18:44 +02:00
Tim Ledbetter
c4d298674b Tests: Re-enable interpolation tests
These run significantly faster than they did when they did when they
were disabled.
2025-05-19 11:31:47 +01:00
Tim Ledbetter
09f4d90594 LibWeb: Clamp interpolated values to the range of their numeric type
This fixes a UBSAN warning that we previously hit when interpolating
color values.
2025-05-19 11:31:47 +01:00
Tim Ledbetter
58ffc56c38 LibWas: Unbreak compilation with WASM_TRACE_DEBUG enabled 2025-05-19 10:20:40 +01:00
Tim Ledbetter
7d7bab7cac LibWeb: Ensure resolved border-width values are non-negative 2025-05-19 09:55:09 +02:00
Ashton
5f5ae6bf8b AK: Replace wchar_t formatting with char32_t
This makes TestFormat fully cross-platform as we no longer have to
work around the 16 vs 32-bit wide strings
2025-05-18 19:18:13 -06:00
Ashton
7f0f513159 AK: Remove unnecessary Aarch64 wchar_t handling
This is legacy from the Serenity codebase, but given there are no
consumers using wchar_t in Ladybird, this can be removed.
2025-05-18 19:18:13 -06:00
Ashton
4b3a3b0856 AK: Remove redundant TestPrint test
This test was only useful when AK/PrintfImplementation.h existed. But
that was removed 11 months ago, so since then this has just been
testing std library functions not implemented by us.
2025-05-18 19:18:13 -06:00
Andrew Kaster
4d039fc3d4 LibWeb+WebWorker: Create SharedWorkerGlobalScope for Shared Workers
Also push the onconnect event for the initial connection.

This still doesn't properly handle sending an onconnect event to a
pre-existing SharedWorkerGlobalScope with the same name for the same
origin, but it does give us a lot of WPT passes in the SharedWorker
category.
2025-05-18 17:50:05 -06:00
Andrew Kaster
978a3b7321 LibWeb: Move AgentType enum to its own header 2025-05-18 17:50:05 -06:00
Andrew Kaster
4af0daf3eb LibWeb: Check actual WorkerGlobalScope subclass to set top level origin
Checking against DedicatedWorkerHost was probably a typo.
2025-05-18 17:50:05 -06:00
Andrew Kaster
62592c19fe LibWeb: Reorganize EmbedderPolicy to shrink the size by 8 bytes 2025-05-18 17:50:05 -06:00
Andrew Kaster
b10a98b0cb LibWeb: Move name attribute to WorkerGlobalScope from subclasses
Also refactor the other properties of WorkerGlobalScope to match the
spec better.
2025-05-18 17:50:05 -06:00
Andreas Kling
cef9564728 LibWeb: Only serialize CSS numbers with up to 5 decimals
This fixes an issue where we'd serialize some floating point numbers
with excessive precision, resulting in unpleasant-looking numbers like
0.49999999999999999 and such.

At least 90 new subtests passing on WPT, possibly more. :^)
2025-05-18 17:23:34 +02:00
Andreas Kling
f813c495ae Tests: Import a WPT test for sin(), cos() and tan() serialization 2025-05-18 17:23:34 +02:00
Andreas Kling
734bc2a0ea AK: Strip trailing zero decimals in default formatting of float numbers
This gives us a more human-looking serialization of numbers by default,
and in case a fixed number of decimal digits is actually wanted, we
still have the 'f' specifier.
2025-05-18 17:23:34 +02:00
Jelle Raaijmakers
e004be7a08 LibWeb: Resolve editing FIXMEs related to unimplemented commands
We have implemented all commands in the editing spec that potentially
reference one another, so we can now rely on the fact that any command
that gets passed to these methods has a definition. User-provided
commands still get checked by means of `queryCommandSupported()` and
friends.

No functional changes.
2025-05-18 14:37:56 +12:00
Daniel Bertalan
33dbe385ce AK: Replace CallableWrapper::destroy() with a destructor
Previously, heap-allocated `CallableWrapper` objects were destroyed in a
very roundabout way: `AK::Function` would call a virtual `destroy()`
method, which then invoked delete manually. This was unnecessary, since
`CallableWrapper` already has a virtual destructor — deleting it through
a `CallableWrapperBase*` correctly calls the closure's destructor.

This fixes GCC `-Wfree-nonheap-object` false positive warnings (#4721)
and coincidentally removes 8 KB of vtable entries (and the corresponding
relative relocations) from LibJS.
2025-05-17 15:07:42 -06:00
Aliaksandr Kalenik
b559965448 LibJS+LibWeb: Replace StringOrSymbol usage with PropertyKey
- Avoids unnecessary conversions between StringOrSymbol and PropertyKey
  on the hot path of property access.
- Simplifies the code by removing StringOrSymbol and using PropertyKey
  directly. There was no reason to have a separate StringOrSymbol type
  representing the same data as PropertyKey, just with the index key
  stored as a string.

PropertyKey has been updated to use a tagged pointer instead of a
Variant, so it still occupies 8 bytes, same as StringOrSymbol.

12% improvement on JetStream/gcc-loops.cpp.js
12% improvement on MicroBench/object-assign.js
7% improvement on MicroBench/object-keys.js
2025-05-17 10:08:37 -04:00
Shannon Booth
5495531118 LibJS: Implement 'less than' for a String over code units
...Instead of code points.
2025-05-17 08:00:59 -04:00
Shannon Booth
d1a40b7951 LibWeb/Infra: Use Utf16View for code_unit_less_than
The Utf16View implemention is a more effecient implementation
and less code overall.
2025-05-17 08:00:59 -04:00
Shannon Booth
5cf87dcfdc AK: Add a Utf16View::is_code_unit_less_than helper
This seems like the natural place to put this since it is specific
to UTF-16.
2025-05-17 08:00:59 -04:00
Sam Atkins
233022c473 LibWeb/CSS: Allow empty trailing group when parsing comma-separated list
There's discussion in the linked spec issue, but the short version is,
this algorithm will see "foo,bar," as a list of two groups, with "foo"
in the first group and "bar" in the second. However, users of this want
to get a list of three groups, with the last one being empty. So, do
that!
2025-05-17 07:53:24 +01:00
Sam Atkins
338282f74d LibWeb/CSS: Treat x resolution unit separately from dppx
Tests show that we need to preserve whether x or dppx units were used,
so the simplest way is to treat them separately.
2025-05-17 07:53:24 +01:00
Sam Atkins
443f9e5afb LibWeb/CSS: Make dimension types serialize in resolved form
Some dimensions would always serialize in a canonical unit, others never
did, and others we manually would do so in their StyleValue. This
commit moves all of that into the dimension types, which means for
example that Length can apply its special rounding.

Our local serialization test now produces the same output as other
browsers. :^)
2025-05-17 07:53:24 +01:00
Sam Atkins
eec4365542 LibWeb/CSS: Extract SerializationMode into its own header
Prep for using this to serialize dimension types, and perhaps other
things in the future.
2025-05-17 07:53:24 +01:00
Sam Atkins
2748522924 Tests: Import matchMedia() test 2025-05-17 07:53:24 +01:00
Callum Law
2bb40b615a LibWeb: Allow parsing of <quirky-color> 2025-05-17 06:47:55 +01:00
Daniel Bertalan
2058fb1144 CMake: Set CMAKE_POSITION_INDEPENDENT_CODE instead of manual -fPIC
If we are doing a statically linked build, there is no need for full
`-fPIC`, just `-fpie` is enough (which lets the compiler assume that
global variables can be accessed directly without the GOT, etc.). CMake
does the right thing already when we set the `POSITION_INDEPENDENT_CODE`
property.
2025-05-16 17:40:49 -06:00
Sam Atkins
ffdf0268dd LibWeb/CSS: Make debug messages in parse_simple_selector() more useful 2025-05-17 00:30:44 +02:00
Sam Atkins
7de5032e73 LibWeb/CSS: Serialize the initial combinator of relative selectors
Selector::serialize() is used for both normal and relative selectors.
For the latter, we need to serialize their initial combinator, and for
the former, we always set the initial combinator as None anyway, so
this would be a no-op there.

Gets us 3 WPT passes.
2025-05-17 00:30:44 +02:00
Sam Atkins
8536e23674 LibWeb/CSS: Parse an ident in :dir(), not a keyword
The spec requires us to accept any ident here, not just ltr/rtl, and
also serialize it back out. That means we need to keep the original
string around.

In order to not call keyword_from_string() every time we want to match
a :dir() selector, we still attempt to parse the keyword and keep it
around.

A small behaviour change is that now we'll serialize the ident with its
original casing, instead of always lowercase. Chrome and Firefox
disagree on this, so I think either is fine until that can be
officially decided.

Gets us 2 WPT passes (including 1 from the as-yet-unmerged :dir() test).
2025-05-17 00:30:44 +02:00
Sam Atkins
7aed541ed0 LibWeb/CSS: Automatically serialize functional pseudo-class arguments
The spec gives us a hard-coded list of functional pseudo-classes and how
to serialize them - but this list is incomplete and likely to always be
outdated compared to the list of pseudo-classes that exist. So instead,
use the generated metadata we already have to serialize their arguments
based on their type.

This fixes :dir() and :has(), which previously did not serialize their
arguments.

Gets us 26 passes (including 6 from that as-yet-unmerged :dir() test).
2025-05-17 00:30:44 +02:00
Sam Atkins
5f144f366d Tests: Create a test for :dir() parsing/serialization
Submitted to WPT as https://github.com/web-platform-tests/wpt/pull/52598
but in the meantime here's a local version.

The spec for this isn't super thorough, so the tests are based on how
Chrome and Firefox behave. Specifically, Firefox returns the ltr/rtl
keyword in lowercase but Chrome keeps the original case for it.

We currently fail most of these but that will be fixed in subsequent
commits.
2025-05-17 00:30:44 +02:00
Sam Atkins
26d71207d4 LibWeb/CSS: Treat *|* selector like * when serializing
1 new WPT pass.
2025-05-17 00:30:44 +02:00
Sam Atkins
eb98bd1a36 Tests: Import some selector pseudo-class parsing tests 2025-05-17 00:30:44 +02:00
Jelle Raaijmakers
a1467c22d3 LibWeb: Add new whitespace-preserving editing command
Major browsers seem to preserve `white-space: pre/pre-wrap` styles in a
`<div>` when deleting the current selection through an editing command.
The idiomatic way to support this is to have a command with a "relevant
CSS property" to make sure the value is recorded and restored where
appropriate, however, no such command exists.

Create a custom command (internal to Ladybird) that implements this
behavior.
2025-05-17 00:29:19 +02:00
Jelle Raaijmakers
1c77b42a44 LibWeb: Add two FIXMEs about input events' missing .data value
For both `<input>` and `<textarea>` elements, we actually need to
provide the input events with the strings that were added to them.
2025-05-17 00:29:19 +02:00
Jelle Raaijmakers
e941965b01 LibWeb: Use TemporaryChange instead of ScopeGuard
This is a more idiomatic way to temporarily change a value. No
functional changes.
2025-05-17 00:29:19 +02:00
Jelle Raaijmakers
ac46ec0b2e LibWeb: Start integrating the editing API with user keyboard input
This reworks EventHandler so text insertion, backspace, delete and
return actions are now handled by the Editing API. This was the whole
point of the execCommand spec, to provide an implementation of both
editing commands and the expected editing behavior on user input.

Responsibility of firing the `input` event is moved from EventHandler to
the Editing API, which also gets rid of duplicate events whenever
dealing with `<input>` or `<textarea>` events.

The `beforeinput` event still needs to be fired by `EventHandler`
however, since that is never fired by `execCommand()`.
2025-05-17 00:29:19 +02:00
Andrew Kaster
564f5ca2cc AK: Propagate -U flag to dependencies when built as a static library
We added a weak symbol to AK to support overriding the default assertion
handler for test cases. However, on macOS, we need to explicitly mark
the possibly-null symbol as 'it's ok for this to be undefined'.

When AK is a shared library, the flag can be applied to the link step of
the dylib, but when it's a static library, we need to apply it to the
executable that links against it.
2025-05-16 14:59:44 -06:00
ayeteadoe
656586a0e5 Meta: Enforce symbol annotation for EXPLICIT_SYMBOL_EXPORT on Windows 2025-05-16 14:33:04 -06:00
ayeteadoe
275a180246 LibTest: Remove unused CrashTest infrastructure
Now that all EXPECT_CRASH related macros have been replaced in
favour of using EXPECT_DEATH related macros, CrashTest is no
longer used and can be deleted.
2025-05-16 13:23:32 -06:00
ayeteadoe
744fd91d0b LibTest: Support death tests without child process cloning
A challenge for getting LibTest working on Windows has always
been CrashTest. It implements death tests similar to Google Test
where a child process is cloned to invoke the expression that
should abort/terminate the program. Then the exit code of the
child is used by the parent test process to verify if the
application correctly aborted/terminated due to invoking
the expression.

The problem was that finding an equivalent way to port Crash::run()
to Windows was not looking very likely as publicly exposed Win32/
Native APIs have no equivalent to fork(); however, Windows actually
does have native support for process cloning via undocumented NT
APIs that clever people reverse engineered and published, see
`NtCreateUserProcess()`.

All that being said, this `EXPECT_DEATH()` implementation avoids
needing to use a child process in general, allowing us to remove
CrashTest in favour of a single cross-platform solution for death
tests.
2025-05-16 13:23:32 -06:00
ayeteadoe
dc707e6ed8 AK: Expose ak_assertion_handler weak symbol for custom death handling
When a `VERIFY()` assertion fails `ak_verification_failed` is invoked
which means the program will invoke `__builtin_trap` and immediately
quit. But with this change we have now allowed for an optional hook
into `ak_*_failed` that lets us perform some custom
action before program exits. This foundation is what we will
(ab)use to implement death tests without the process cloning
CrashTest infrastructure.
2025-05-16 13:23:32 -06:00
ayeteadoe
d35486cb74 LibTest: Explicitly export symbols 2025-05-16 13:23:32 -06:00
Andreas Kling
2194cbde4b LibWeb: Stub out SVGGraphicsElement.getCTM()
We already did this for getScreenCTM().
2025-05-16 20:36:07 +02:00
Andreas Kling
1dc6425ede LibWeb: Implement SVGElement.viewportElement 2025-05-16 20:36:07 +02:00
Andreas Kling
879cba762b LibWeb: Implement Document.rootElement (SVG2 extension to Document) 2025-05-16 20:36:07 +02:00
Andreas Kling
e6f75801b1 LibWeb: Import WPT test for checking all the basic SVG interfaces exist 2025-05-16 20:36:07 +02:00
Jelle Raaijmakers
170e599bd9 LibWeb: Always set the Y offset of the current block in BFC
Originally part of a fix in 15103d172c, it
appears that this is no longer necessary and received a better fix in a
more recent commit. Resolves a visual regression with the ACID3 test.
2025-05-16 20:33:27 +02:00
Sam Atkins
c9484e279f LibWeb/CSS: Implement CSSPageRule.setSelectorText()
Gets us 12 WPT subtest passes.
2025-05-16 16:42:10 +01:00
Sam Atkins
d852ae17e8 LibWeb/CSS: Make @page selector parsing accessible
Mostly minor changes - the code has moved, and has to support Token or
ComponentValue TokenStreams, but otherwise it's the same.
2025-05-16 16:42:10 +01:00
Sam Atkins
107b47f884 LibWeb/CSS: Move PageSelector into its own files
The main motivation here is that the CSS Parser needs to know about
PageSelectorList so that we can parse one in
`CSSPageRule::set_selector_text()`. Including all of `CSSPageRule.h`
there would pull in a lot of other headers that aren't needed.
2025-05-16 16:42:10 +01:00
Sam Atkins
869abe0b21 LibWeb/CSS: Match *-namespace selectors against all attributes
Previously we only matched against the first attribute with a given
local name. What we actually want to do is look at each attribute with
that local name in turn and only return false if none of them match.

Also remove a hack for HTML elements in HTML documents, where we would
refuse to match any namespaced attributes. This doesn't seem to be
based on the spec, but we had regressions without it, until now. :^)

Gets us 21 more WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
ecdfb96a0a LibWeb/CSS: Limit case-insensitive default comparison to HTML attributes
The HTML spec gives us a list of HTML attributes that must have their
values compared case-insensitively by default (when the attribute
selector does not specify a case-sensitiveness). However, ifwe have a
namespace, then we are not looking for an HTML attribute, so this
should not apply.

Gets us 8 more WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
d9113e45f0 LibWeb/CSS: Discard trailing whitespace inside attribute selectors
This gets us 84 more subtests, so everything in this syntax test passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
3914bf05fb LibWeb/CSS: Serialize * namespace in attribute selectors
Gets us 13 WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
a56ce0f6fa Tests: Import attribute-selector case-sensitivity tests 2025-05-16 16:41:57 +01:00
aplefull
68ddc7006d LibMedia: Implement conversion of BT601 primaries 2025-05-16 12:13:13 +01:00
stelar7
9e7fb5efbc LibWeb/IDB: Update spec step wording 2025-05-16 12:10:16 +01:00
stelar7
c1d63b5b28 LibWeb/IDB: Implement queue_a_database_task 2025-05-16 12:10:16 +01:00
Jelle Raaijmakers
29f1648bc5 LibWeb: Do not override whitespace handling for editable elements
This condition no longer seems to be necessary for anything, and it
caused newlines to not render correctly in editable nodes.
2025-05-16 12:08:29 +01:00
Jelle Raaijmakers
a48e693ea1 LibWeb: Add tests for styleWithCSS and useCSS editing commands 2025-05-16 12:07:35 +01:00
Sam Atkins
870f24f181 LibWeb/CSS: Add basic implementation of CSSMarginRule
This is a bit under-specced, specifically there's no definition of
CSSMarginDescriptors so I've gone with CSSStyleProperties for now. Gets
us 17 WPT subtests.
2025-05-16 11:01:39 +01:00
Sam Atkins
aa9fa88428 LibWeb/CSS: Treat at-rule names insensitively to determine context type
`@MeDiA` is entirely valid.
2025-05-16 11:01:39 +01:00
Sam Atkins
101f6b1d7e Tests: Import CSSMarginRule tests 2025-05-16 11:01:39 +01:00
Tim Ledbetter
2903defcfc Revert "LibJS+LibWeb: Return Vector<PropertyKey> from…
internal_own_property_keys"

This reverts commit 5ee810f772.
2025-05-16 06:33:09 +01:00
Tim Ledbetter
8cd9275416 Revert "LibJS: Ensure keys vector capacity in…
Object::internal_own_property_keys"

This reverts commit 27ba216e3f.
2025-05-16 06:33:09 +01:00
Sam Atkins
3f18331594 LibWeb/HTML: Do not allow named window targeting with noopener
Corresponds to dfdafb4b29

We fail the test for this, but we actually do create the separate popup
windows correctly (when popups aren't blocked!) but the test checks
`window.name` which we incorrectly return the empty string for.
https://wpt.live/html/browsers/windows/auxiliary-browsing-contexts/named-lookup-noopener.html
2025-05-16 10:21:09 +12:00
Sam Atkins
08419a6d8f LibWeb/HTML: Correct show_popover() invocations
Corresponds to 47f854c66e
2025-05-16 10:21:09 +12:00
Sam Atkins
2efad4c941 LibWeb/HTML: Fire load event for non-string javascript: URLs
Corresponds to 8abe559982

The relevant test doesn't pass, so we're probably missing some other
part of this mechanism:
https://wpt.live/html/semantics/embedded-content/the-embed-element/embed-javascript-url.html
2025-05-16 10:21:09 +12:00
Aliaksandr Kalenik
27ba216e3f LibJS: Ensure keys vector capacity in Object::internal_own_property_keys
12% improvement on MicroBench/object-keys.js
2025-05-15 14:12:18 -04:00
Aliaksandr Kalenik
5ee810f772 LibJS+LibWeb: Return Vector<PropertyKey> from internal_own_property_keys
By doing that we avoid lots of `PropertyKey` -> `Value` -> `PropertyKey`
transforms, which are quite expensive because of underlying
`FlyString` -> `PrimitiveString` -> `FlyString` conversions.

10% improvement on MicroBench/object-keys.js
2025-05-15 14:12:18 -04:00
Timothy Flynn
47569c1714 CI: Do not install clang in the JS benchmarks workflow
It's not needed. This is primarily to reduce the number of places needed
to be updated on the next clang rollout.
2025-05-15 18:53:49 +02:00
Sam Atkins
1fe29ac642 LibWeb/CSS: Bring :lang() matching closer to spec
With this, we pass the 8 ref tests in css/selectors/selectors-4/ which
previously failed. This is not technically a full implementation, as we
are supposed to first canonicalize the language range and tag, but that
will require downloading and processing the IANA language subtag
registry:

https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

That's significantly more work, and WPT doesn't seem to test any cases
that require that, so we can leave it for now.
2025-05-15 16:40:44 +01:00
Ben Eidson
e0e513e9fc LibWeb/MimeSniff: Add WebM signature sniffing and VINT parsing
Adds `matches_webm_signature()` and `parse_vint()` helpers per WPT
spec. Uses these helpers to resolve the WebM FIXME that was in
`match_an_audio_or_video_type_pattern()`.
2025-05-15 09:39:19 -06:00
R-Goc
20662f0dc9 AK: Add windows support in AK/Random
This commit adds support in AK/Random for a high quality RNG on windows.
This requires moving the code into a cpp file not to spread windows
headers around.
2025-05-15 07:41:02 -06:00
R-Goc
d60543c2cb LibJS/LibCrypto: Cleanup JS Math random() RNG
This commit adds a convenience method to secure random for initializing
single types. It changes the random number generator in JS math random()
to use newer constants by the author as well as initializes it with a
higher quality seed.
2025-05-15 07:41:02 -06:00
Andrew Kaster
a01d6ba246 CMake: Clear CMAKE_REQUIRED_LIBRARIES after blocks and arc tests
This is better CMake hygiene to avoid leaking our try_compile specific
library requirements into the rest of the build.
2025-05-15 07:20:20 -06:00
Jelle Raaijmakers
9f044cb547 CI: Only add LLVM repository if it is missing
For our js-benchmarks and libjs-test262 workflow runs, we already know
that they're provisioned with these repositories and can skip adding the
key and repo altogether.
2025-05-15 15:13:55 +02:00
Jelle Raaijmakers
44db17f273 CI: Switch from wget to curl
We were using both wget and curl arbitrarily; use curl exclusively since
that is installed by default on our machines and containers. Fixes the
js-benchmarks workflow.
2025-05-15 14:22:38 +02:00
Tim Ledbetter
1c5881c44a LibCore: Remove LADYBIRD_GIT_VERSION environment variable usage
This was previously used by the WPT runner to determine the git hash
of a particular WPT run. This mechanism is no longer used, since it
doesn't work with chunked WPT runs.
2025-05-15 14:02:48 +02:00
Tim Ledbetter
7f4916b806 Meta: Ensure wptreport browser_version field is always populated
This was previously done by passing the `LADYBIRD_GIT_VERSION`
environment variable to `wpt`, but this doesn't work in chunked mode.
2025-05-15 14:02:48 +02:00
Jelle Raaijmakers
cac1d49d21 LibWeb: Ensure we're not creating invalid ranges
Our Ranges should maintain the invariant that their offsets are always
within range of 0..length (inclusive) of their respective containers.

Note that we cannot maintain this in AbstractRange, which is the base
for StaticRange and can still have invalid offsets.
2025-05-15 11:44:32 +01:00
Jelle Raaijmakers
c3a5e8e266 LibWeb: Invalidate viewport's text blocks cache on layout update
156c1083e9 introduced a text blocks cache
for better performance when searching through text on a page, but when
we partially recreate the layout tree, this cache does not get
invalidated. We now rebuild the entire text blocks cache after a layout
update.
2025-05-15 11:44:32 +01:00
Jelle Raaijmakers
0d83426a49 LibWeb: Modify range start & end directly where applicable
We were calling into `Range::set_start_or_end()` indirectly through
`::set_start()` and `::set_end()`, but that algorithm only calls for an
invocation whenever the start or end of a range needs to be set to a
boundary point. If an algorithm step calls for setting the node or
offset, we should directly modify the range.

The problem with calling into `::set_start_or_end()` is that this
algorithm potentially modifies _both_ the start and end of the range,
but algorithms trying to update a range's start or end often have
explicit steps to take both the start and end into account and end up
overcompensating for the start or end offset resulting in an invalid
range (e.g. with an end offset beyond a node's length).

This makes updating a range's start/end a bit more efficient and removes
a piece of ad-hoc code in CharacterData needed to make it work before.
2025-05-15 11:44:32 +01:00
Tim Ledbetter
e2db9790b0 Meta: Use human readable timestamp in WPT run folder name
This makes it easier to figure out when a given run started.
2025-05-15 12:11:20 +02:00
Sam Atkins
3a235e9050 LibWeb/CSS: Parse @page bleed, marks, page-orientation descriptors
These don't have WPT tests so I've added some myself.
2025-05-15 09:53:29 +01:00
Sam Atkins
9415bffd9b LibWeb/CSS: Parse @page size descriptor 2025-05-15 09:53:29 +01:00
Sam Atkins
d8c6b872a3 LibWeb/CSS: Allow descriptors to be shorthands
I was wrong when I added those notes before about this being impossible,
it's *very* possible, for example with the `@page margin` descriptor.
However, until we have a large number of these shorthands and not just a
single example, we can get away with hard-coding support for it.
2025-05-15 09:53:29 +01:00
Sam Atkins
1aa5631610 LibWeb/CSS: Parse @page selectors
Ideally we'd be able to share the code between page selectors and style
ones, but given how simple page selectors are, some code duplication is
the simpler option.
2025-05-15 09:53:29 +01:00
Sam Atkins
aaf07ae30d LibWeb: Add basic implementation of @page
This doesn't support selectors, and the only descriptors for now are for
margins.
2025-05-15 09:53:29 +01:00
Sam Atkins
1002464322 Tests: Import WPT CSSOM and parsing tests for @page 2025-05-15 09:53:29 +01:00
Andrew Kaster
09ed4bd265 CI: Manually add apt repo for llvm 20 to all relevant jobs 2025-05-14 19:43:52 -04:00
Andrew Kaster
30d01f7920 Devcontainer: Update to llvm 20 2025-05-14 19:43:52 -04:00
Andrew Kaster
096bd2369a Documentation: Remove instructions for OpenIndiana
No one has tried to build Ladybird on this Solaris fork since the
fork, and it doesn't have any vcpkg support.
2025-05-14 22:15:40 +01:00
Andrew Kaster
cd06939325 Documentation: Remove instructions for Haiku
No one has tried to build Ladybird on Haiku since the
fork, and it doesn't have any vcpkg support.
2025-05-14 22:15:40 +01:00
stelar7
22a7e0795a LibWeb/IDB: Use helper method for checking transaction mode 2025-05-14 17:17:29 +02:00
stelar7
c8e1b24864 LibWeb/IDB: Use helper method for checking transaction state 2025-05-14 17:17:29 +02:00
stelar7
4c7c7845d3 LibWeb/IDB: Remove outdated FIXME 2025-05-14 17:17:29 +02:00
stelar7
13674c1b32 LibWeb/IDB: Resolve FIXME regarding removing from indecies 2025-05-14 17:17:29 +02:00
stelar7
46ecf239c4 LibWeb/IDB: Implement storing of index records 2025-05-14 17:17:29 +02:00
stelar7
c73b8d1fa0 LibWeb/IDB: Implement IDBIndex::openKeyCursor 2025-05-14 17:17:29 +02:00
stelar7
852323009f LibWeb/IDB: Implement IDBIndex::count 2025-05-14 17:17:29 +02:00
stelar7
b8bb8345a9 LibWeb/IDB: Implement IDBIndex::getAllKeys 2025-05-14 17:17:29 +02:00
stelar7
3fa1d1299c LibWeb/IDB: Implement IDBIndex::getAll 2025-05-14 17:17:29 +02:00
stelar7
47450bc15c LibWeb/IDB: Implement IDBIndex::getKey 2025-05-14 17:17:29 +02:00
stelar7
e74e571b56 LibWeb/IDB: Implement IDBIndex::get 2025-05-14 17:17:29 +02:00
Sam Atkins
73fa567e7a LibWeb/CSS: Remove now-unused AllowUnresolved enum
This mechanism has been replaced with PendingSubstitutionValues.
2025-05-14 11:46:47 +01:00
Sam Atkins
4edafb35cd LibWeb/CSS: Use PendingSubstitutionValue for unresolved shorthands
Previously, we would just assign the UnresolvedStyleValue to each
longhand, which was completely wrong but happened to work if it was a
ShorthandStyleValue (because that's basically a list of "set property X
to Y", and doesn't care which property it's the value of).

For example, the included `var-in-margin-shorthand.html` test would:
1. Set `margin-top` to `var(--a) 10px`
2. Resolve it to `margin-top: 5px 10px`
3. Reject that as invalid

What now happens is:
1. Set `margin-top` to a PendingSubstitutionValue
2. Resolve `margin` to `5px 10px`
3. Expand that out into its longhands
4. `margin-top` is `5px` 🎉

In order to support this, `for_each_property_expanding_shorthands()` now
runs the callback for the shorthand too if it's an unresolved or
pending-substitution value. This is so that we can store those in the
CascadedProperties until they can be resolved - otherwise, by the time
we want to resolve them, we don't have them any more.

`cascade_declarations()` has an unfortunate hack: it tracks, for each
declaration, which properties have already been given values, so that
it can avoid overwriting an actual value with a pending one. This is
necessary because of the unfortunate way that CSSStyleProperties holds
expanded longhands, and not just the original declarations. The spec
disagrees with itself about this, but we do need to do that expansion
for `element.style` to work correctly. This HashTable is unfortunate
but it does solve the problem until a better solution can be found.
2025-05-14 11:46:47 +01:00
Sam Atkins
398d2f9981 LibWeb/CSS: Implement pending-substitution value
This is a special value temporarily assigned to longhands when their
shorthand is unresolved, and then later replaced once that is resolved.
2025-05-14 11:46:47 +01:00
Sam Atkins
59e8a669de LibWeb/CSS: Unify code in StyleComputer::cascade_declarations() 2025-05-14 11:46:47 +01:00
Sam Atkins
d1dadd43a1 LibWeb/CSS: Implement guaranteed-invalid value
This is a special value produced when var/attr substitution fails, and
is also the initial value for custom properties.
2025-05-14 11:46:47 +01:00
Sam Atkins
804c1eeeed LibWeb/CSS: Remove double set_property_expanding_shorthands() call
If `value` was UnresolvedStyleValue, we'd attempt to `set_property...()`
with its resolved value, then call that again with the original
UnresolvedStyleValue. For any other kind of `value`, we'd simply call
call `set_property...()` twice with the same parameters.
2025-05-14 11:46:47 +01:00
Sam Atkins
ded3c95da5 LibWeb/CSS: Remove unused FontVariant style value type 2025-05-14 11:46:47 +01:00
Sam Atkins
475788732f LibWeb/CSS: Remove outdated FIXME
This method no longer sets anything to `initial`.
2025-05-14 11:46:47 +01:00
R-Goc
34c14d4e6d LibJS: Add fast path for float to int put
This commit adds a fast path for putting values into a TypedArray of an
integer type, when the value being put in is a double. This leads to a
6% speedup on JetStream/gcc-loops.js.
2025-05-14 12:33:35 +02:00
ayeteadoe
0061c64ee6 CMake: Remove duplicate sanitizer configuration
Root had identical copy of what was being done in Meta/Lagom
so now we ensure this is still included globally but is
isolated to its own cmake module to make sanitizer
config easier to discover
2025-05-14 02:05:12 -06:00
ayeteadoe
c4f08bc268 CMake: Add LibDiff to TEST_DIRECTORIES
Not sure if it has always been this way, but Tests/LibDiff has
not actually been running in CI at all.
2025-05-14 02:05:12 -06:00
ayeteadoe
11bca38f91 CMake: Build LibRegex tests in Tests/LibRegex not Meta/Lagom
As LibRegex was not specified in TEST_DIRECTORIES, the existing
Tests/LibRegex subdirectory was not actually included during
configuration. Also the RegexLibC test has not been needed
since migration away from Serenitys LibC was done, so
that test has been fully removed. I also renamed the
Regex.cpp test to TestRegex.cpp to match the naming
convention of most test targets.
2025-05-14 02:05:12 -06:00
ayeteadoe
8864b3e9d1 CMake: Build LibCore tests in Tests/LibCore not Meta/Lagom
As LibCore was not specified in TEST_DIRECTORIES, the existing
Tests/LibCore subdirectory was not actually included during
configuration.
2025-05-14 02:05:12 -06:00
ayeteadoe
d44ac0874f CMake: Build LibTest[Main] in Libraries/LibTest not Meta/Lagom
As LibTest was not specified in TEST_DIRECTORIES, the existing
Libraries/LibTest subdirectory was not actually included during
configuration.
2025-05-14 02:05:12 -06:00
Timothy Flynn
7280ed6312 Meta: Enforce newlines around namespaces
This has come up several times during code review, so let's just enforce
it using a new clang-format 20 option.
2025-05-14 02:01:59 -06:00
Timothy Flynn
ca9f3673c5 Everywhere: Run clang-format
The following command was used to clang-format these files:

    clang-format-20 -i $(find . \
        -not \( -path "./\.*" -prune \) \
        -not \( -path "./Build/*" -prune \) \
        -not \( -path "./Toolchain/*" -prune \) \
        -type f -name "*.cpp" -o -name "*.mm" -o -name "*.h")
2025-05-14 02:01:59 -06:00
Timothy Flynn
d30f6f1b11 Meta: Switch to clang-format-20 as the standard formatter 2025-05-14 02:01:59 -06:00
Timothy Flynn
313e490fb6 Meta: Extract the required clang-format version to a variable
Rather than writing the version N times in this script, let's extract it
to a variable for easier use.
2025-05-14 02:01:59 -06:00
Timothy Flynn
70d2b0b6f3 CI: Update the Clang pipeline to Clang 20 2025-05-14 02:01:59 -06:00
Timothy Flynn
a65bbae4c9 CI: Update the GCC pipeline to GCC 14
Although GCC 15 is released, it is not available on Ubuntu 22.04 LTS via
the ubuntu-toolchain-r/test PPA.
2025-05-14 02:01:59 -06:00
Timothy Flynn
6fc7483757 Documentation: Bump OpenIndiana's clang version
Clang 19 seems to be the newest available:
https://pkg.openindiana.org/hipster/en/search.shtml?token=clang&action=Search

It also looks like they have newer versions of GCC now, but let's just
advise clang on this system that no contributer is using.
2025-05-14 02:01:59 -06:00
Timothy Flynn
0e4a2f760f Documentation: Refer to specific compiler versions in fewer places
The required and recommended compiler versions are sort of scattered
across several documents. Let's list them in a single document, and
have other documents refer to that location.

The language here intentionally recommends the same compiler versions
used in CI. The find_compiler.sh script can be updated with the
minimum known good version.
2025-05-14 02:01:59 -06:00
Timothy Flynn
85ee56a702 CI: Use clang for the test262 build
We currently have optimizations that apply only to clang, so we might as
well make use of them.
2025-05-14 02:01:59 -06:00
Timothy Flynn
3d59efa7e1 CI: Use clang for the fuzzer's lagom tools build
It's kind of weird to be mixing gcc and clang here.
2025-05-14 02:01:59 -06:00
Andrew Kaster
c7cfd3cb1e CI: Disable LTO by default for static GCC builds
lto1 uses more memory than exists in the known universe when building
ladybird, so disable LTO for static GCC builds.
2025-05-14 02:01:50 -06:00
Andrew Kaster
905c5ecb4c AK: Silence -Wfree-nonheap-object more generally in Function for gcc
We were already silencing it at the site of the delete call, but gcc in
distribution mode is more aggressive about inlining and still sees a
delete that it doesn't like.
2025-05-14 02:01:50 -06:00
mikiubo
89e0896cd7 LibWeb: Implement XML Char validation for Text node serialization
With this fix, the second test in domparsing/innerhtml-01.xhtml passes.
2025-05-14 18:18:08 +12:00
Glenn Skrzypczak
5c578b6057 LibWeb/HTML: Implement report_validity
This implements the previously stubbed out `report_validity` method.

The specification is not very clear on how to exactly report the
validity. For now, we bring the first visible invalid control into
view and focus it. In the future, however, it would make sense to
support more complex scenarios and be more aligned with the other
implementations.
2025-05-14 09:39:12 +12:00
stelar7
296d9d74d8 LibWeb/IDB: Implement IDBCursorWithValue interface 2025-05-13 10:48:40 -06:00
stelar7
9c51326fcb LibWeb/IDB: Implement IDBCursor::delete 2025-05-13 10:48:40 -06:00
stelar7
cf84a98bab LibWeb/IDB: Implement IDBCursor::update 2025-05-13 10:48:40 -06:00
stelar7
3154ac8988 LibWeb/IDB: Implement IDBCursor::continuePrimaryKey 2025-05-13 10:48:40 -06:00
stelar7
6afa2c8eee LibWeb/IDB: Implement IDBCursor::advance 2025-05-13 10:48:40 -06:00
stelar7
82d17fa17e LibWeb/IDB: Sort IDBCursor fields according to IDL 2025-05-13 10:48:40 -06:00
Psychpsyo
a0be82b2cb LibWeb: Move containment checks to Layout::Node
It fits better there and avoids having to reach into the Element
all the time.
2025-05-13 15:30:14 +03:00
Psychpsyo
4989c5c793 LibWeb: Add paint containment clipping
The contain-paint-stacking-context-001a.html test has been removed
for now because it has a 1px tall blue line at the top that should
not be there. With paint containment, this line is removed only in
the actual test case, but not in the reference. This is because of
the font that we use in testing and happens in Chromium as well if
the test is run with that font.
2025-05-13 15:30:14 +03:00
Psychpsyo
ed7374783d LibWeb: Enable different overflow along the x and y axis 2025-05-13 15:30:14 +03:00
Psychpsyo
85883ee5ce LibWeb: Deduplicate clipping code
This makes it so that PaintableWithLines no longer has its own
bespoke clipping logic, using the same code as regular scroll/
overflow clipping.
2025-05-13 15:30:14 +03:00
Aliaksandr Kalenik
155e60a5ff LibJS: Use iteration_step() in IteratorNextUnpack instruction
Allows us to avoid code duplication for builtin iterators fast path.
2025-05-13 15:14:25 +03:00
Aliaksandr Kalenik
bb53485dea LibJS+LibWeb: Add fast path for builtin iterators in iterator_step()
We already have fast path for built-in iterators that skips `next()`
lookup and iteration result object allocation applied for `for..of` and
`for..in` loops. This change extends it to `iterator_step()` to cover
`Array.from()`, `[...arr]` and many other cases.

Makes following function go 2.35x faster on my computer:
```js
(function f() {
  let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  for (let i = 0; i < 1000000; i++) {
    let [a, ...rest] = arr;
  }
})();
```
2025-05-13 15:14:25 +03:00
Psychpsyo
31301ef08b LibWeb: Add support for trees of pseudo-elements
This is needed for CSS view transitions.
2025-05-13 12:38:42 +01:00
stelar7
a2ecafb968 LibWeb/IDB: Use enum flags in IDBKeyRange 2025-05-13 22:46:43 +12:00
stelar7
a5023ec053 LibWeb/IDB: Use enum flags in IDBCursor 2025-05-13 22:46:43 +12:00
Shannon Booth
41b060be81 LibDiff: Remove a bunch of unused code
We have no need to support normal or context diffs in ladybird,
as well as the ability to parse and apply patches.
2025-05-13 12:46:34 +02:00
Tim Ledbetter
03e34db9f8 LibWeb: Interpolate the content-visibility property correctly 2025-05-13 11:24:05 +01:00
Tim Ledbetter
882ad4726e LibWeb: Interpolate the visibility property correctly 2025-05-13 11:24:05 +01:00
Psychpsyo
f52df06a2a LibWeb: Do not forget to unapply empty masks 2025-05-13 10:31:08 +02:00
Andrew Kaster
0402179331 CMake: Disable C++20 module scanning
We don't use C++20 modules, and CMake will look for clang-scan-deps in
clang builds if this setting is not disabled. This is a problem when
clang-scan-deps is not installed, as it will cause CMake to fail to link
hidden visibility libraries properly.
2025-05-12 23:43:59 -06:00
Psychpsyo
c105f99547 Meta: Add doctypes to all grid layout tests 2025-05-13 03:49:32 +03:00
Psychpsyo
1fa3b16c8c Meta: Add doctypes to some flex layout tests
This adds doctypes to all the remaining flexbox layout tests.
2025-05-12 23:15:06 +01:00
stelar7
a11efe3139 LibWeb/IDB: Sort IDBObjectStore according to the IDL 2025-05-13 08:27:52 +12:00
stelar7
7250aa0b6b LibWeb/IDB: Implement IDBObjectStore::getAllKeys 2025-05-13 08:27:52 +12:00
stelar7
927237c736 LibWeb/IDB: Implement retrieve_multiple_keys_from_an_object_store 2025-05-13 08:27:52 +12:00
stelar7
c56ec49ce6 LibWeb/IDB: Implement IDBObjectStore::openKeyCursor 2025-05-13 08:27:52 +12:00
stelar7
c700bfaaf1 LibWeb/IDB: Implement IDBObjectStore::getAll 2025-05-13 08:27:52 +12:00
stelar7
ddaae635ac LibWeb/IDB: Implement retrieve_multiple_values_from_an_object_store 2025-05-13 08:27:52 +12:00
stelar7
7f98d708ef LibWeb/IDB: Implement IDBObjectStore::getKey 2025-05-13 08:27:52 +12:00
stelar7
c47ddf11ba LibWeb/IDB: Implement retrieve_a_key_from_an_object_store 2025-05-13 08:27:52 +12:00
Andrew Kaster
09c794d40d Tests: Bump lit to version 18.1.8 for ClangPlugins tests 2025-05-12 16:00:55 -04:00
Andrew Kaster
27503a5320 Tests: Invoke clang frontend instead of cc1 in ClangPlugin tests
Reverts 7fcedae610 at the same time
2025-05-12 16:00:55 -04:00
Daniel Bertalan
a2167f126d Everywhere: Fix trivial -Wunnecessary-virtual-specifier instances
- `Threading::Thread` is not polymorphic, there is no need for a virtual
  destructor.
- `HTMLAnchorElement::has_download_preference` isn't overridden by
  anything.

This warning was introduced in llvm/llvm-project#131188.
2025-05-12 11:40:45 -06:00
Daniel Bertalan
456d750539 LibJS: Make generate_labelled_evaluation non-virtual if possible
We don't override anything with definitions of this function in
`SwitchStatement` and `LabelledStatement`. Also, we can make the
`IterationStatement` abstract, there is no need to add a fallback
error-generating stub implementation of this method.
2025-05-12 11:40:45 -06:00
Daniel Bertalan
6b08a52c8b LibGC: Make destructors non-virtual where possible
`ConservativeVector`, `RootVector` and `RootHashMap` are final types,
and their base classes have a protected destructor, so when their
destructor is called, the static and dynamic types will be the same
(can't destruct them through a pointer to a base or derived class).
Therefore, there is no need for a virtual destructor.

This fixes the newly introduced `-Wunnecessary-virtual-specifier`
Clang warning (llvm/llvm-project#131188).
2025-05-12 11:40:45 -06:00
Mikkel Krautz
c48a78e37f LibWeb: Fix copyright headers with inconsistent > characters 2025-05-12 11:21:04 -06:00
Andrew Kaster
c0f0f45b6e Documentation: Add clang-tools to the Ubuntu/Debian build instructions
When using non-BFD linkers, something about our CMake setup causes
visibility checks from GenerateExportHeader to fail when clang-scan-deps
is not found.
2025-05-12 10:40:43 -06:00
Aliaksandr Kalenik
f405d71657 LibJS: Disable optimization in IteratorNextUnpack if next() is redefined
81b6a11 regressed correctness by always bypassing the `next()` method
resolution for built-in iterators, causing incorrect behavior when
`next()` was redefined on built-in prototypes. This change fixes the
issue by storing a flag on built-in prototypes indicating whether
`next()` has ever been redefined.
2025-05-12 07:41:29 -04:00
Andrew Kaster
a6d9e8acd8 CMake: Only find pthread and mman on Windows once
This reduces a lot of CMake spam when configuring
2025-05-12 03:22:23 -06:00
ayeteadoe
a3754a7bf1 LibRegex: Annotate classes with export macro for hidden visibility
This fix demos the gradual opt-in migration process libraries can
take to switch to explicit symbol exports via the FOO_API macros.
2025-05-12 03:22:23 -06:00
Andrew Kaster
3dd2fbd041 LibRegex: Move StringTable ctor/dtor out of line
This also moves the next_serial class static into a file scope static.
The public class static was causing visibility issues with certain Linux
builds when hidden visibility was enabled. However, the current design
makes more sense anyway :^).
2025-05-12 03:22:23 -06:00
ayeteadoe
8f670950e2 Meta: Add opt-in explicit symbol export for libraries
On Windows, `set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)` is currently
used. But that will need to change as LibWeb exceeds the maximum
symbols that can be exported from a single executable/dll
(See LNK1189 error). So to prevent bitrot and Unix/Windows getting
out of sync, this function that generates the export header for the
target also sets the symbol visibility to hidden on Unix to ensure
Link errors also occur on Unix if the the required library components
are not annotated with the FOO_API macro.
2025-05-12 03:22:23 -06:00
ayeteadoe
0253342c1a LibRegex: Use NO_UNIQUE_ADDRESS in RegexMatch for Windows support
Clang's `x86_64-pc-windows-msvc` target requires
`[[msvc::no_unique_address]]`, which is properly set in the
`NO_UNIQUE_ADDRESS` macro in `AK/Platform.h`. Without this, building
on Windows fails due to `-Wunknown-attributes`.
2025-05-12 03:22:23 -06:00
Andrew Kaster
fc6237325b CI: Install clang-tools-19 to ensure clang-scan-deps is available 2025-05-12 03:22:23 -06:00
Shannon Booth
b478274e0b LibWeb: Use infra sorting for URLSearchParam's sort()
Adopts editiorial change to the URL spec of:

https://github.com/whatwg/url/commit/59979a1
2025-05-12 11:20:32 +02:00
Shannon Booth
74334ea1ce LibWeb: Only use code unit length for is_code_unit_prefix
Fixes a crash in the included test.
2025-05-12 11:20:32 +02:00
Shannon Booth
1cd09724f1 LibWeb/Infra: Ignore OOM for utf16 conversion in 'is code unit prefix' 2025-05-12 11:20:32 +02:00
Psychpsyo
91159df0dd LibWeb: Draw text even if it needs to go into a 0-size inline box 2025-05-12 10:49:46 +02:00
Andreas Kling
096eed35cc LibWeb: Avoid O(n^2) traversal in play-or-cancel-animations logic
The play_or_cancel_animations_after_display_property_change() helper
was being called by Node::inserted() and Node::removed_from() and then
recursing into the shadow-including subtree.

This had quadratic complexity since inserted() and removed_from() are
themselves already invoked recursively for everything in the
shadow-including subtree.

Only one caller of this API actually needed the recursive behavior,
so this patch moves that responsibility to the caller and puts the logic
in style recomputation instead.

1.02x speedup on Speedometer's TodoMVC-jQuery.
2025-05-11 20:22:17 +02:00
Timothy Flynn
1a9e78a774 LibWebView: Disable autocomplete when search is disabled
Search suggestions don't make much sense when search itself is disabled.
We now auto-disable autocomplete when search is disabled.
2025-05-11 11:48:02 -04:00
Timothy Flynn
9267172e28 Base: Simplify enabling search and autocomplete
Currently, enabling search is a bit hokey. You have to click a checkbox
to get the search engines to show up, then you have to click a drop down
to select an engine. Let's go with a simpler approach; now you only have
to interact with the drop down.
2025-05-11 11:48:02 -04:00
Timothy Flynn
840157191d Base: Name the settings .dialog-description class a bit more generic
It will be used outside of dialogs.
2025-05-11 11:48:02 -04:00
Andreas Kling
a0864dbb26 LibJS: Make mapped arguments objects way less allocation-happy
By following the spec to the letter, our mapped arguments objects ended
up with many extra GC allocations:

- 1 extra Object for the internal [[ParameterMap]].
- 2 extra NativeFunctions for each mapped parameter accessor.
- 1 extra Accessor to hold the aforementioned NativeFunctions.

This patch removes all those allocations and lets ArgumentsObject model
the desired behavior in custom C++ instead of using script primitives.

1.06x speedup on Speedometer's TodoMVC-jQuery.
2025-05-11 14:00:40 +02:00
Timothy Flynn
a71d909b39 AK: Remove unused Error functionality 2025-05-10 21:19:46 -04:00
Timothy Flynn
08e82ddaf0 LibCore: Prefer Error::is_errno over Error::is_syscall
These are the only users of the latter, so let's just use is_errno
(which will effectively give us the same result) to avoid confusion
over these.
2025-05-10 21:19:46 -04:00
Timothy Flynn
95441dabd5 AK: Define some simple getters in a single line
This matches our coding style everywhere else. clang-format used to have
trouble with these, but it doesn't any longer.
2025-05-10 21:19:46 -04:00
Timothy Flynn
dceed08058 AK+LibCore: Avoid double-negation of syscall error values
This is a remnant from SerenityOS. Let's avoid confusion as to why we
negate errno when we call Error::from_syscall just to negate it again
when we store the error code.
2025-05-10 21:19:46 -04:00
Timothy Flynn
24ac5e2eee AK+LibCore: Remove SerenityOS handling from Error and Core::System
This is just to make some syscall error handling changes simpler.
2025-05-10 21:19:46 -04:00
Timothy Flynn
4f132b9e40 AK: Remove Error::from_string_view_or_print_error_and_return_errno
This was for use within Serenity's kernel. In Ladybird, it is just some
indirection to Error::from_string_view.
2025-05-10 21:19:46 -04:00
Timothy Flynn
e2b863ed3f AK: Remove unused Jakt methods 2025-05-10 21:19:46 -04:00
InvalidUsernameException
029bcf13fd Libweb: Invalidate layout for the value-attribute of li-elements 2025-05-11 01:14:31 +02:00
InvalidUsernameException
370098514a LibWeb: Invalidate layout for ol-attributes that affect it 2025-05-11 01:14:31 +02:00
Andreas Kling
263b125782 LibWeb: Let HTMLTokenizer walk over code points instead of UTF-8
Instead of using UTF-8 iterators to traverse the HTMLTokenizer input
stream one code point at a time, we now do a one-shot conversion up
front from the input encoding to a Vector<u32> of Unicode code points.

This simplifies the tokenizer logic somewhat, and ends up being faster
as well, so win-win.

1.02x speedup on Speedometer 2.1
2025-05-11 01:13:20 +02:00
R-Goc
7cccdb3bcf AK: Fix error is_errno
Previously the check for is_errno did not check if the error kind was
syscall, which also set errno so that behavior was incorrect.
2025-05-10 11:25:12 -04:00
Shannon Booth
29ac95a3e2 LibJS: Remove unused VM::on_call_stack_emptied 2025-05-10 08:19:03 -04:00
R-Goc
79b652c74e AK: Rework error types to store kind as an enum
This commit makes windows errors store the code instead of being a
formatted string literal. This will allow comparing against the error,
and checking what it is. The formatting is now done in the formatter,
and moved to an implementation file to avoid polluting headers with
windows.h. The kind of the error is now determined by an enum Kind which
will allow matching against the error kind.

Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-05-10 00:03:31 -06:00
Andrew Kaster
f0004fa690 AK+CMake: Remove workaround for swiftc mishandling [[no_unique_address]] 2025-05-09 23:14:27 -06:00
Andrew Kaster
ac6b99800b CI: Bump swift snapshot to main-snapshot-2025-04-30 2025-05-09 23:14:27 -06:00
Andrew Kaster
accb77fda9 LibWeb: Add missing WebIDL/Types include to MediaCapabilities.h
This causes a build failure when building a clang module for LibWeb.
2025-05-09 23:14:27 -06:00
aplefull
7da2339c89 LibGfx: Properly skip IDAT chunks without fcTL in APNG files
In the previous fix, we were still drawing IDAT data to the reference
frame even when no fcTL was present. This would cause rendering issues
when subsequent frames use APNG_BLEND_OP_OVER blending mode, as they
would composite over the incorrect reference frame. This commit adds a
simple check to properly skip any frame without an fcTL chunk.
2025-05-09 21:45:29 +02:00
aplefull
e5944a4d9e LibGfx: Correctly handle OS/2 BMPs with 3-byte color entries
We now properly handle OS/2 format BMPs that use 3 bytes per color
entry instead of 4. While OS/2 2.x officially specified 4 bytes per
color, some tools still produce files with 3-byte entries. We can
identify such files by checking the available color table space.
2025-05-09 21:45:29 +02:00
aplefull
4d8717fa3a LibGfx: Add .cur file support to ICO loader
This extends ICO loader to support Windows cursor files. There is no
point in creating a separate loader for this, as the ICO format is
very similar to the CUR format. The only differences are bytes used to
identify the file and a presence of a hotspot in the CUR header.
2025-05-09 21:45:29 +02:00
aplefull
48ca895f5f LibGfx: Properly skip color masks in BMP V2+ headers
Color masks should only be used when the compression type is either
BITFIELDS or ALPHABITFIELDS. They were always read before and produced
corrupted images when there was random data in the mask fields.
2025-05-09 21:45:29 +02:00
aplefull
c908c14aac LibGfx: Clamp BMP color palette to 1024
Other browsers don't think that BMP files with more than 1024 colors are
invalid. They clamp the palette instead, and now we do the same. This
allows us to load more BMPs.
2025-05-09 21:45:29 +02:00
Jelle Raaijmakers
70b52e0994 LibWeb: Use efficient background repeat path for either direction
We're able to efficiently draw repeated bitmaps through Skia, but for
backgrounds we only did so if the background was `repeat-x` _and_
`repeat-y`, and not if just one was set. This meant that for backgrounds
that were only repeating in one direction, we were taking the slow path.
Turns out that this slow path also produced graphical artifacts when
zooming in and out, so let's not do that :^)
2025-05-09 21:37:48 +02:00
Timothy Flynn
30e8f3f1ad LibWeb: Update the <details> layout tree when it is opened/closed
Otherwise, the arrow painted next to the <details> element does not
update.

Using a screenshot test here because apparently the direction of the
arrow has no effect on the layout or paint trees.
2025-05-09 21:37:14 +02:00
Andreas Kling
6efc5c54b5 AK: Make Utf16View::to_utf8() use simdutf fast path more often
By piggybacking on the already-optimized implementation in
StringBuilder, we can get simdutf for the AllowInvalidCodeUnits::Yes
case here as well.

1.03x speedup on Speedometer's TodoMVC-jQuery.
2025-05-09 21:36:59 +02:00
Andreas Kling
f61df9d34c LibWeb: Don't throw away UA shadow trees willy-nilly
We were unnecessarily discarding the shadow trees of various elements
when they were removed or detached from the DOM.

This especially caused a *lot* of churn when creating input elements via
setting .innerHTML on something. We ended up building each input
element's shadow tree 3 times instead of 1.

The original issue that we were trying to solve by discarding shadow
trees appears to have been solved elsewhere, and nothing else seems to
break by just allowing them to remain in place.

1.05x speedup on Speedometer's TodoMVC-jQuery.
2025-05-09 12:49:04 -04:00
Jelle Raaijmakers
123abe0e79 LibWeb: Overlap float space and left margins for all shared ancestors
We would only correct for the left margin of the containing block of the
child box that we are laying out, but we actually need to correct for
all left margins up until the containing block that contains both the
float and the child box.

Fixes #4639.
2025-05-09 14:13:02 +02:00
Aliaksandr Kalenik
6530f55f34 LibJS: Cache rejected/fulfilled callbacks in AsyncFunctionDriverWrapper
Saves us two NativeFunction allocations per each `await`.

With this change, following function goes 80% faster on my computer:
```js
(async () => {
    const resolved = Promise.resolve();
    for (let i = 0; i < 5_000_000; i++) {
        await resolved;
    }
})();
```
2025-05-09 12:30:15 +02:00
Aliaksandr Kalenik
4c789ac689 LibJS: Skip iteration result allocation in AsyncFunctionDriverWrapper
- Create less GC pressure by making each `await` in async function skip
  iteration result object allocation.
- Skip uncached `Object::get()` calls to extract `value` and `done` from
  the iteration result object.

With this change, following function goes 30% faster on my computer:
```js
(async () => {
    const resolved = Promise.resolve();
    for (let i = 0; i < 5_000_000; i++) {
        await resolved;
    }
})();
```
2025-05-09 12:30:15 +02:00
Shannon Booth
286a9d8101 LibJS: Don't run promise and cleanup jobs in Interpreter::run
https://tc39.es/ecma262/#sec-jobs specifies that we should only be
running queued promise jobs and host-defined cleanup when the
execution context stack is empty. It is asserted to _not_ be empty
the line above, so remove it.

No impact on test262 or our test suites, Interpreter::run_executable
is already (incorrectly) performing this unconditionally.
run_promise_jobs also happens to do nothing when LibJS is embedded
into LibWeb.
2025-05-09 09:35:49 +02:00
Ali Mohammad Pur
43defa90cc Meta: Make WPT.sh log args relative to cwd as of script invocation
This restores the behaviour from before adding parallel instance
support.
2025-05-08 23:50:04 +01:00
Shannon Booth
19bf897116 LibJS: Avoid roundtrip through Value for comparison bytecode evaluation
1.1x speedup on strictly-equals-object.js
2025-05-08 20:39:29 +02:00
Sam Atkins
90d466e7e9 LibWeb: Add dumping code for keyframe/keyframes rules 2025-05-08 16:21:32 +01:00
Sam Atkins
fbdef98307 LibWeb: Dump CSSDescriptors in a generic way
This replaces the need for bespoke (and verbose) dumping for each
at-rule that has descriptors.
2025-05-08 16:21:32 +01:00
Sam Atkins
f0ce4f43a6 LibWeb: Make unknown webkit pseudo-elements safe to dump
This fixes a couple of crashes when dumping the style sheets on
ladybird.org
2025-05-08 16:21:32 +01:00
Sam Atkins
0925a32558 LibWeb/CSS: Extract a CSSDescriptors base class
This holds the boilerplate that's needed by any CSSStyleDeclaration
subclass that holds Descriptors. CSSFontFaceDescriptors now only has to
worry about initialization and its own exposed properties.
2025-05-08 16:21:32 +01:00
Kenneth Myhra
6941b63890 LibWeb: Add {,de}serialization steps for ImageData 2025-05-09 02:12:01 +12:00
Kenneth Myhra
5b4644d198 LibWeb: Use WebIDL types for IDL exposed attributes 2025-05-09 02:12:01 +12:00
Kenneth Myhra
306c7b8211 Tests: Import some structuredClone-related WPT tests 2025-05-09 02:12:01 +12:00
Timothy Flynn
5eb4c3dc2f LibWebView: Disable spare WebContent processes when profiling WebContent
Each WebContent process will create a callgrind log file. Let's not log
processes we are not interested in.
2025-05-08 10:02:41 -04:00
Timothy Flynn
4916ae6d67 LibWebView: Paint callgrind instructions a bit less aggressively
On my terminal, the colors chosen before were very hard to read.
2025-05-08 10:02:41 -04:00
Sam Atkins
15356b7036 Documentation: Mention requirements for ENABLE_CLANG_PLUGINS 2025-05-08 10:02:10 -04:00
stelar7
fa207c8fc6 LibWeb/IDB: Implement IDBObjectStore::clear 2025-05-08 14:13:21 +01:00
stelar7
637f35c0eb LibWeb/IDB: Implement clear_an_object_store 2025-05-08 14:13:21 +01:00
stelar7
aa35ced34f LibWeb/IDB: Implement IDBObjectStore::delete 2025-05-08 14:13:21 +01:00
stelar7
1fe6060ff9 LibWeb/IDB: Improve error messages slightly 2025-05-08 14:13:21 +01:00
stelar7
63e1cc7b50 LibWeb/IDB: Implement IDBIndex::open_cursor 2025-05-08 14:13:21 +01:00
stelar7
8f876e824b LibWeb/IDB: Implement IDBCursor::primary_key 2025-05-08 14:13:21 +01:00
stelar7
141093e032 LibWeb/IDB: Implement IDBCursor::effective_key 2025-05-08 14:13:21 +01:00
Jelle Raaijmakers
f996fb9d80 LibWeb: Translate special WebDriver keys for backspace, tab and return
These private code points are used extensively by WebDriver clients,
such as the WPT suite.
2025-05-08 07:06:02 -04:00
Bastiaan van der Plaat
0b6f693636 UI/AppKit: Use webview layout event instead of window resize events
Currently the window resize events are used to resize the webview.
But when extra window items appear, for example: search or DevTools
Bar then the webview is clipped out of the window. This also happens
when the tab bar is opened and closed. Listening to layout events
resolves these clipping issues completely.
2025-05-08 11:23:21 +01:00
Bastiaan van der Plaat
5a3b98e0a9 UI/AppKit: Disable toolbar mode customization
Currently you can right click on the toolbar for a system
contextmenu. When you change the display mode
the toolbar goes into a weird smaller state.
2025-05-08 11:23:21 +01:00
Timothy Flynn
c846616d51 LibWeb: Adjust positions by the scroll offset for scrollbar hit testing
This ensures we scroll to the correct position when dragging a scrollbar
or clicking its gutter.
2025-05-08 10:40:58 +01:00
Timothy Flynn
22532c769c LibWeb: Be less lenient in scrollbar hit testing
A scrollbar contains a mouse position only if its gutter rect contains
that position. We were incorrectly deciding a position was contained if
it fell to the right of a vertical scrollbar, or below a horizontal
scrollbar.
2025-05-08 10:40:58 +01:00
Sam Atkins
a8529629e2 LibWeb/HTML: Update "is script closable" to current spec
Corresponds to d7fc63a84a
and 7a48703e77
2025-05-08 10:39:34 +01:00
Ali Mohammad Pur
292688e249 LibWasm: Validate tables, memories, globals, elements and data correctly
These sections are supposed to be validated with only the imported
globals.
2025-05-08 03:35:11 -06:00
Ali Mohammad Pur
1bcbd008d6 Tests/LibWeb: Rebaseline some no-longer-failing wasm tests 2025-05-08 03:35:11 -06:00
Ali Mohammad Pur
638a354b29 LibWeb/WebAssembly: Throw appropriate errors as defined by the spec 2025-05-08 03:35:11 -06:00
Ali Mohammad Pur
333ba93d49 LibWeb/WebAssembly: Define the hacky 'native' errors given in the spec
These cannot be implemented "correctly" as the set of native errors as
defined by ecma262 is closed, but we can get pretty close.
2025-05-08 03:35:11 -06:00
Ali Mohammad Pur
fbfd3e2538 IDLGenerators: Add an 'WithInitializer' attribute for an init hook
This is needed for WebAssembly.*Error (at least), which apparently
cannot be defined in webidl.
2025-05-08 03:35:11 -06:00
Andrew Kaster
8a57b75969 Devcontainer: Update fedora devcontainer to version 42 2025-05-08 03:21:15 -06:00
Andrew Kaster
3c8515a1a1 Documentation: Add patchelf as a dependency for on Fedora
The provided patchelf from vcpkg is only version 0.14.3, which is too
old to produce working binaries on Fedora 42. Using that old version
causes hard to debug issues where applications segfault during startup.
2025-05-08 03:21:15 -06:00
Francesco Gazzetta
5610f5a865 LibWeb/HTML: Add missing include to CanvasRenderingContext2D.cpp
Fixes linking of CanvasRenderingContext2D on some systems:

    [2959/3075] Linking CXX shared library lib/liblagom-web.so.0.0.0
    FAILED: lib/liblagom-web.so.0.0.0
    : && /nix/store/f0m6caffiykyvsjim9376a3hx2yj2ghj-gcc-wrapper-14.2.1.20250322/bin/g++ -fPIC -O3 -DNDEBUG  -fstack-protector-strong -Wl,-z,defs -Wl,--no-undefined -Wl,--no-allow-shlib-undefined -Wl,--dependency-file=Lagom/Libraries/LibWeb/CMakeFiles/LibWeb.dir/link.d -shared -Wl,-soname,liblagom-web.so.0 -o lib/liblagom-web.so.0.0.0 @CMakeFiles/LibWeb.rsp && :
    /nix/store/hzw38c3f7s0w200cgk9645z53al7k8lw-binutils-2.44/bin/ld: Lagom/Libraries/LibWeb/CMakeFiles/LibWeb.dir/HTML/CanvasRenderingContext2D.cpp.o: in function `Web::HTML::CanvasRenderingContext2D::context_attributes_from_options(JS::VM&, JS::Value) [clone .localalias]':
    CanvasRenderingContext2D.cpp:(.text+0x355a): undefined reference to `JS::Value::to_boolean() const'
    /nix/store/hzw38c3f7s0w200cgk9645z53al7k8lw-binutils-2.44/bin/ld: CanvasRenderingContext2D.cpp:(.text+0x38e6): undefined reference to `JS::Value::to_boolean() const'
    /nix/store/hzw38c3f7s0w200cgk9645z53al7k8lw-binutils-2.44/bin/ld: CanvasRenderingContext2D.cpp:(.text+0x3d67): undefined reference to `JS::Value::to_boolean() const'
    collect2: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.

Co-authored-by: Timothy Flynn <trflynn89@pm.me>
2025-05-07 16:53:09 -04:00
Ali Mohammad Pur
011982c501 Meta: Make WPT.sh run nproc/2 testrunners in parallel
This is the "intended" way of parallelism with wpt, but instead of
requiring N different systems (or VMs), this does it all on one system
with the power of namespaces.
2025-05-07 15:48:21 +01:00
Ali Mohammad Pur
79c32f33e1 Meta: Reformat WPT.sh 2025-05-07 15:48:21 +01:00
Jelle Raaijmakers
d424dc1b32 LibWeb: Assign new wrapped node list to container for insertParagraph
Forgot to implement this part of the spec.
2025-05-07 16:11:31 +02:00
Jelle Raaijmakers
c56f7d9cde LibWeb: Invalidate sibling style for :only-child and :*-of-type
After f7a3f785a8, sibling nodes' styles
were no longer invalidated after a node was removed. This reuses the
flag for `:first-child` and `:last-child` to indicate that a node's
style might be affected by any structural change in its siblings.

Fixes #4631.

Resolves the `:only-child` ACID3 failure as documented in #1231.
2025-05-07 14:55:12 +03:00
Andreas Kling
74f133293d LibJS: Avoid redundant ExecutionContext allocation for bound functions
Instead of creating a second ExecutionContext in BoundFunction.[[Call]],
we now implement BoundFunction::get_stack_frame_size() and combine
information from the target + the bound arguments list.

This allows BoundFunction.[[Call]] to reuse the already-established
ExecutionContext for the callee.

1.20x speedup on MicroBench/bound-call-04-args.js
2025-05-07 13:20:41 +02:00
Psychpsyo
dbece92637 LibWeb: Make elements with 'opacity: 0' respond to hit-testing 2025-05-07 01:45:07 +03:00
Andreas Kling
d462731a4d LibJS: Make PutById inline cache polymorphic (4 shapes)
2.44x speedup on MicroBench/pic-put-own.js
1.48x speedup on MicroBench/pic-put-pchain.js
2025-05-07 00:27:11 +02:00
Andreas Kling
a677d96b8f LibJS: Make GetById cache polymorphic
Instead of monomorphic (1 shape), GetById inline caches are now
polymorphic (4 shapes).

This improves inline cache hit rates greatly on most web JavaScript.
For example, Speedometer 2.1 sees 88% -> 97% cache hit rate improvement.

1.71x speedup on MicroBench/pic-get-own.js
1.82x speedup on MicroBench/pic-get-pchain.js
2025-05-07 00:27:11 +02:00
enkvadrat
678c15a06a UI/Qt: Add Ctrl-R shortcut for page Reload
Keeping things consistent with other browsers
where both f5 and Ctr-R can be used to reload.
2025-05-07 10:20:51 +12:00
Psychpsyo
86f2d291ca Meta: Add HTML doctype to a screenshot test that should have it 2025-05-06 20:04:18 +02:00
Lyra
39dae6fb2d LibWeb: Fix SRI handling of badly-formatted strings 2025-05-06 13:02:58 -04:00
Timothy Flynn
0da7441b9b LibWeb: Set the initiator type for script-initiated CSS requests
Similar to other ad-hoc behavior in this method, we need to handle
requests which are not associated with a style sheet. For example:

    <script>
        const element = document.createElement('div');
        element.style['background'] = 'url(https://foo.com/img.png)';
        document.body.appendChild(element);
    </script>

Will not be associated with a style sheet.

This is needed to ensure we fire a PerformanceResourceTiming event for
this resource load. This is not currently testable in CI, as this event
is also gated by HTTP/S requests.
2025-05-06 17:37:34 +01:00
InvalidUsernameException
1d63398cbd AK: Expose dump_backtrace() publicly for debugging purposes
At this point, I've repeatedly felt the desire to be able to log
stacktraces to be able to see more easily what kind of call-sites exist
for a given piece of code. So this commit exposes `dump_backtrace()` in
the header so it can be used for this purpose.
2025-05-06 10:03:57 -04:00
Golho
0c2db2ab35 Documentation: Update VSCodeConfiguration.md
- Update debug description for debugging on Linux with VSCode
- Update build paths in documentation
2025-05-06 10:00:01 -04:00
Timothy Flynn
4fc8443757 LibWeb: Translate scrollbar gutters by the cumulative scroll offset
This `translate_by` function is invoked with the cumulative scroll
offset during display list execution. Applying the offset to the gutter
was missed in 66e422b4f1.
2025-05-06 16:38:23 +03:00
stelar7
9d5f6108e4 LibWeb/IDB: Implement recent spec changes 2025-05-06 13:30:37 +01:00
Mark Langen
6cbb5d2785 LibWeb: Parse and propagate touch-action CSS property
Co-authored-by: Sam Atkins <sam@ladybird.org>
2025-05-06 12:22:01 +01:00
Aliaksandr Kalenik
b3713db4ab LibJS: Emit ThrowIfTDZ for identifiers used in assignment expressions
Error about not-initialized `x` variable access should be thrown for:
```js
function foo() {
    x = 69;
    let x;
}

foo();
```

Progress on test262:
```
Diff Tests:
test/staging/sm/expressions/optional-chain-tdz.js  -> 
test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js
 -> 
```

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4587
2025-05-06 12:06:23 +02:00
Aliaksandr Kalenik
db480b1f0c LibJS: Preserve information about local variables declaration kind
This is required for upcoming change where we want to emit ThrowIfTDZ
for assignment expressions only for lexical declarations.
2025-05-06 12:06:23 +02:00
stelar7
2774068ca0 LibWeb/IDB: Initialize the index set in a ObjectStore handle 2025-05-06 11:16:01 +02:00
stelar7
0ed71d87ca LibWeb/IDB: Dont move away the name when creating an Index 2025-05-06 11:16:01 +02:00
stelar7
f3a31c98ea LibWeb/IDB: Use correct key comparison when doing Index lookup 2025-05-06 11:16:01 +02:00
stelar7
64c4bea189 LibWeb/IDB: Implement IDBCursor::continue 2025-05-06 11:16:01 +02:00
stelar7
f5eb7928d9 Meta/IDL: Add continue as a cpp keyword 2025-05-06 11:16:01 +02:00
stelar7
08f73db773 LibWeb/IDB: Return undefined if request was an error 2025-05-06 11:16:01 +02:00
stelar7
d0156e2c88 LibWeb/IDB: Use invalidation reason when returning DataError 2025-05-06 11:16:01 +02:00
stelar7
05fe37619a LibWeb/IDB: Implement IDBObjectStore::open_cursor 2025-05-06 11:16:01 +02:00
stelar7
98d08b27e4 LibWeb/IDB: Implement iterate_a_cursor 2025-05-06 11:16:01 +02:00
stelar7
93d7a29306 AK: Implement {first|last}_matching for Span 2025-05-06 11:16:01 +02:00
stelar7
0890b10d11 LibWeb/IDB: Improve error messages related to transaction state 2025-05-06 11:16:01 +02:00
sideshowbarker
6237824d99 Tests: Add a bunch of input-element tests (tests only, no code)
Importing these tests now because they are for input-element types that
have requirements related to the constraint-validation API — which we’ve
been implementing recently.

This commit only imports tests, without any changes to our code.
2025-05-06 09:46:49 +01:00
Bastiaan van der Plaat
58b735010b LibWeb: Add -webkit-box-* legacy CSS property aliases 2025-05-05 23:36:31 +02:00
Andreas Kling
183c847c80 LibJS: Cache PutById to setters in the prototype chain
This is *extremely* common on the web, but barely shows up at all in
JavaScript benchmarks.

A typical example is setting Element.innerHTML on a HTMLDivElement.
HTMLDivElement doesn't have innerHTML, so it has to travel up the
prototype chain until it finds it.

Before this change, we didn't cache this at all, so we had to travel
the prototype chain every time a setter like this was used.

We now use the same mechanism we already had for GetBydId and cache
PutById setter accesses in the prototype chain as well.

1.74x speedup on MicroBench/setter-in-prototype-chain.js
2025-05-05 15:21:43 +02:00
Jelle Raaijmakers
71665fa504 LibWeb: Scale font size by 1.15 for line-height: normal
Browsers such as Chrome and Firefox apply an arbitrary scale to the
current font size if `normal` is used for `line-height`. Firefox uses
1.2 while Chrome uses 1.15. Let's go with the latter for now, it's
relatively easy to change if we ever want to go back on that decision.

This also requires updating the expectations for a lot of layout tests.
The upside of this is that it's a bit easier to compare our layout
results to other browsers', especially Chrome.
2025-05-05 13:15:56 +02:00
Timothy Flynn
01791c5a52 LibJS: Mark sync module evaluation promise as handled
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/0fb1859

As noted in the PR for this change, this is not actually testable via
either test262 or WPT.
2025-05-05 17:50:18 +12:00
Psychpsyo
7c36a82129 LibWeb: Improve parsing for the CSS contain property
This makes us actually respect the grammar and nets us a couple
extra WPT passes in the parsing section.
2025-05-04 22:24:26 +01:00
Timothy Flynn
1c075d6039 LibWeb: Remove Web::Infra ASCII case conversion methods
We have more optimized versions of these methods in AK.
2025-05-04 15:59:17 +02:00
Psychpsyo
d048ee3155 Meta: Add doctypes to all svg layout tests 2025-05-04 11:23:52 +02:00
Psychpsyo
3fd13485ab Meta: Add doctypes to all table layout tests 2025-05-04 11:23:17 +02:00
Andreas Kling
bf1b754e91 LibJS: Optimize reading known-to-be-initialized var bindings
`var` bindings are never in the temporal dead zone (TDZ), and so we
know accessing them will not throw.

We now take advantage of this by having a specialized environment
binding value getter that doesn't check for exceptional cases.

1.08x speedup on JetStream.
2025-05-04 02:31:18 +02:00
Andreas Kling
ad7c1e147f LibJS: Add SetGlobal bytecode instruction for cached global writes
Before this change, setting a global would end up as SetLexicalBinding.
That instruction always failed to cache the access if the global was a
property of the global object.

1.14x speedup on Octane/earley-boyer.js
2.04x speedup on MicroBench/for-of.js

Note that MicroBench/for-of.js was more of a "set global" benchmark
before this. After this change, it's actually a for..of benchmark. :^)
2025-05-04 01:58:57 +02:00
Sam Atkins
de6df6f403 LibWeb/CSS: Parse and use CSS URL request modifiers 2025-05-03 23:22:40 +01:00
Sam Atkins
09b508d8e8 Tests: Import some URL-related WPT tests 2025-05-03 23:22:40 +01:00
Sam Atkins
a1fb34d7f2 LibWeb/CSS: Alphabetize Enums.json 2025-05-03 23:22:40 +01:00
Andreas Kling
edb5547e37 LibJS: Don't incrementally delete PropertyNameIterator while iterating
We were spending a lot of time removing each property name from the
iterator's underlying HashMap while iterating over it. This wasn't
actually necessary, so let's stop doing it and instead just iterate
over the property names with a stored HashTable iterator.

1.10x speedup on MicroBench/for-in-indexed-properties.js
2025-05-03 22:00:51 +02:00
Andreas Kling
c8edd37741 Meta: Add Shannon Booth to maintainers list :^) 2025-05-03 20:58:23 +02:00
Andreas Kling
570d1e8811 LibJS: Use PrimitiveString more instead of Utf16String in String code
This avoids a whole lot of unnecessary roundtrips from UTF8 <=> UTF16.
2025-05-03 20:01:20 +02:00
Andreas Kling
98fef16972 LibJS: Use PrimitiveString more instead of Utf16String in RegExp code
PrimitiveString has an internal UTF-16 string cache anyway, and so this
actually avoids repeatedly converting between UTF-8 and UTF-16.
2025-05-03 20:01:20 +02:00
Jess
897c83cbcb Docs: Link the external Nix devshell 2025-05-03 16:40:50 +01:00
Andreas Kling
7c26354563 LibJS: Avoid Value->PropertyKey->Value roundtrip in for..in iteration
Before this change, we would call [[OwnPropertyKeys]] on the target
objects, then convert the returned keys from Value into PropertyKey.
Then, when actually iterating, we'd convert them back into Value again.
This was particularly costly for numeric property keys, since we had
to go through string-from-number construction.

Now, we simply keep the original values returned by [[OwnPropertyKeys]]
around and use them for the enumeration.

1.09x speedup on MicroBench/for-in-indexed-properties.js
1.01x speedup on MicroBench/for-in-named-properties.js
2025-05-03 17:33:54 +02:00
Andreas Kling
11ece7de10 LibGC: Add GC::RootHashMap<...> template container
This is a GC-aware wrapper around AK::HashMap. Entry values are treated
as GC roots, much like the GC::RootVector we already had.

We also provide GC::OrderedRootHashMap as a convenience.
2025-05-03 17:33:54 +02:00
Andreas Kling
a453da2906 AK: Allow specifying HashSetExistingEntryBehavior in HashMap::set() 2025-05-03 17:33:54 +02:00
Timothy Flynn
8a80ff7b3b AK+LibJS: Use simdutf for all base64 operations
We were previously unable to use simdutf for base64 decoding operations
other than "loose". Upstream has added support for the "strict" and
"stop-before-partial" operations, so let's make use of them!
2025-05-03 11:21:10 -04:00
Timothy Flynn
e04545979f Meta: Update simdutf to version 7.0.0 2025-05-03 11:21:10 -04:00
Timothy Flynn
6b6dd9c998 Meta: Update vcpkg baseline 2025-05-03 11:21:10 -04:00
Shannon Booth
e476d21ed0 LibJS: Add and use PrimitiveString::length_in_utf16_code_units
I was investigating an optimization in this area, and while it
didn't seem to have a noticable improvement, it still seems
useful to apply this change.
2025-05-03 16:18:47 +02:00
Sam Atkins
560317b3d0 LibWeb/CSS: Update spec comment in calc() simplification algorithm
This was corrected in 8bcf3ada9e
2025-05-03 14:54:33 +01:00
Sam Atkins
1cb1526178 LibWeb/CSS: Remove document-URL hack from create_a_style_sheet()
We no longer need this, because we don't complete URLs during parsing,
and the location is set elsewhere when needed.
2025-05-03 12:01:43 +01:00
Sam Atkins
bc1d323ba0 LibWeb/CSS: Remove URL parameter to the CSS Parser
We no longer complete any URLs during parsing.
2025-05-03 12:01:43 +01:00
Sam Atkins
9e2e796f2d LibWeb/CSS: Use CSS::URL for font-fetching
ParsedFontFace and FontLoader now both keep track of which
CSSStyleSheet (if any) was the source of the font-face, so the URLs can
be completed correctly.
2025-05-03 12:01:43 +01:00
Sam Atkins
14fb567a0f LibWeb/CSS: Stop overwriting style sheet location after construction 2025-05-03 12:01:43 +01:00
Sam Atkins
981ede900a LibWeb/DOM: Create style element style sheets with document's base URL
This is the simplest fix I could find that resolves a buggy interaction
between this and the CSS fetch algorithms, which also doesn't regress
anything. (As far as I can tell.)
2025-05-03 12:01:43 +01:00
Sam Atkins
7a4854732a LibWeb/CSS: Make CSS::URL formattable 2025-05-03 12:01:43 +01:00
Sam Atkins
efad6e96aa LibWeb/CSS: Set CSSFontFaceDescriptors' parent rule 2025-05-03 12:01:43 +01:00
Sam Atkins
ffc01626f7 LibWeb/CSS: Load fonts using fetch
Convert FontLoader to use fetch_a_style_resource(). ResourceLoader used
to keep its downloaded data around for us, but fetch doesn't, so we use
Gfx::Typeface::try_load_from_temporary_memory() so that the font has a
permanent copy of that data.
2025-05-03 12:01:43 +01:00
Sam Atkins
1967d5bc75 LibGfx: Add a helper for constructing a TTF font from temporary bytes
Once we switch from ResourceLoader to Fetch, nobody is going to be
holding onto the downloaded data, so we need to make a permanent copy
of it.
2025-05-03 12:01:43 +01:00
Sam Atkins
f76f8dcce1 LibWeb/CSS: Return the FetchController from fetch_a_style_resource() 2025-05-03 12:01:43 +01:00
Sam Atkins
6b762331df LibGfx: Rename WOFF[2]::try_load_from_externally_owned_memory()
Typeface::try_load_from_externally_owned_memory() relies on that
external owner keeping the memory around. However, neither WOFF nor
WOFF2 do so - they both create separate ByteBuffers to hold the TTF
data. So, rename them to make it clearer that they don't have any
requirements on the byte owner.
2025-05-03 12:01:43 +01:00
Tim Ledbetter
23009779e1 LibWeb: Interpolate font-style values correctly
These are interpolated by computed value, except a value of `normal` is
treated as `oblique 0deg`.
2025-05-03 12:05:22 +02:00
Tim Ledbetter
c0f9b11070 LibWeb: Parse oblique font-style with an angle value 2025-05-03 12:05:22 +02:00
Andreas Kling
e537e426c1 LibJS: Teach for..in iterator to use IteratorNextUnpack optimization
Even though this code was already optimized to re-use a single result
object, returning { value, done } directly in output parameters still
provides a substantial speedup.

1.21x speedup on MicroBench/for-in-indexed-properties.js
2025-05-03 11:43:57 +02:00
Andreas Kling
0ef6444824 LibJS: Replace some use of ByteString with String
1.19x speedup on MicroBench/for-in-indexed-properties.js
2025-05-03 08:08:04 +02:00
Andreas Kling
2ef2e75cdc LibJS: Reduce HashTable rehashing in get_object_property_iterator()
Apply a little ensure_capacity() to avoid excessive rehashing of the
property key table when enumerating a large number of properties.

1.23x speedup on MicroBench/for-in-indexed-properties.js
2025-05-03 08:08:04 +02:00
Timothy Flynn
ea77092100 LibWeb: Begin implementing SharedWorker
Shared workers are essentially just workers that may be accessed from
scripts within the same origin. There are plenty of FIXMEs here (mostly
building on existing worker FIXMEs that are already in place), but this
lets us run the shared worker variants of WPT tests.
2025-05-02 17:48:02 -04:00
Timothy Flynn
469d5ccc4b LibWeb: Add FIXME about Worker's constructor's scriptURL parameter
TrustedScriptURL is its own interface that we haven't implemented yet.
2025-05-02 17:48:02 -04:00
Timothy Flynn
56f047119c LibWeb: Alphabetically sort LibWeb sources
I sorted this list when added shared worker sources, and this is the
fallout.
2025-05-02 17:48:02 -04:00
Timothy Flynn
912009f6b3 LibWeb: Implement navigator.clipboard.read 2025-05-02 17:46:16 -04:00
Timothy Flynn
a4e9a27343 LibWeb: Implement navigator.clipboard.write 2025-05-02 17:46:16 -04:00
Timothy Flynn
a1985e57e7 LibWeb: Implement navigator.clipboard.readText 2025-05-02 17:46:16 -04:00
Timothy Flynn
7f8f72556a headless-browser: Implement a stubbed clipboard API
We currently rely on UI-specific APIs to interact with the system
clipboard from AppKit and Qt. We do not have access to these from
headless-browser.

We should ultimately implement these APIs without relying on the UI as
a middle-man. For now, store a clipboard item so that we may exercise
the clipboard WPT tests.
2025-05-02 17:46:16 -04:00
Timothy Flynn
61c0f67c8c LibWeb+LibWebVew+WebContent+UI: Add IPC to retrieve the system clipboard
We currently have a single IPC to set clipboard data. We will also need
an IPC to retrieve that data from the UI. This defines system clipboard
data in LibWeb to handle this transfer, and adds the IPC to provide it.
2025-05-02 17:46:16 -04:00
Timothy Flynn
5fb5066e89 LibWeb: Initialize plain boolean in ClipboardItem::Representation 2025-05-02 17:46:16 -04:00
Timothy Flynn
4a9ed67e9d LibWeb: Do not store clipboard items in an unprotected vector 2025-05-02 17:46:16 -04:00
Andreas Kling
cf6e2531d9 AK: Make String::number() much faster for integer types
Instead of going through String::formatted(), we now have a specialized
code path for base-10 serialization directly to UTF-8.

This is roughly 5-10x faster than the previous implementation, depending
on how many digits we end up outputting.

1.07x speedup on MicroBench/for-in-indexed-properties.js
2025-05-02 19:13:03 +02:00
Bastiaan van der Plaat
4d84e1a8bc Base: Add about:settings and about:processes to about:about page 2025-05-02 12:21:37 +02:00
Bastiaan van der Plaat
832bb978f5 LibWeb: Reject CSS values with unprocessed tokens / extra semicolons 2025-05-02 11:10:02 +01:00
Bastiaan van der Plaat
b99f4872d1 LibWeb: Allow transform calculated length properties 2025-05-02 11:10:02 +01:00
Tim Ledbetter
542c3cbe51 LibWeb: Implement the transition-behavior CSS property
This specifies whether transitions should be started for transitions
whose animation behavior is discrete.
2025-05-02 11:07:19 +01:00
Jelle Raaijmakers
e57e38dafc LibWeb: Use as_if<T> in TreeNode methods
Using `as<T>` calls into `as_if<T>`, so let's just immediately use
that for the "node of type" iterators. No functional changes.
2025-05-02 11:02:20 +02:00
Aliaksandr Kalenik
6426586052 LibJS: Skip "return" method call while closing built-in iterators
"return" method is not defined on any of builtin iterators, so we could
skip it, avoiding method lookup.

I measured 10% improvement in array-destructuring-assignment.js micro
benchmark with this change.
2025-05-01 18:17:06 +02:00
Sam Atkins
6d2f393f2b LibGC: Make GC::Root formattable 2025-05-01 17:16:04 +01:00
Sam Atkins
06d62e5b5a LibGC: Make GC::Ptr and GC::Ref formattable
This is a copy of the Formatters we have for AK's pointer types.
2025-05-01 17:16:04 +01:00
Aliaksandr Kalenik
60bd5012fe LibJS: Optimize array destructuring assignment for builtin iterators
...by avoiding `{ value, done }` iterator result value allocation. This
change applies the same otimization 81b6a11 added for `for..in` and
`for..of`.

Makes following micro benchmark go 22% faster on my computer:
```js
function f() {
    const arr = [];
    for (let i = 0; i < 10_000_000; i++) {
        arr.push([i]);
    }
    let sum = 0;
    for (let [i] of arr) {
        sum += i;
    }
}

f();
```
2025-05-01 16:57:56 +03:00
Jelle Raaijmakers
295b78f7d3 LibWeb: Do not rely on the layout tree for collapsed line breaks
The editing command that relies the most on this, `insertLinebreak`,
did not perform a layout update after inserting a `<br>` which caused
this algorithm to always return false. But instead of actually building
the layout tree needlessly, we can check the DOM tree instead.
2025-05-01 15:44:26 +03:00
aplefull
71a4e18bf8 LibGfx: Only include frames with fcTL chunks in the animation
Before this change, IDAT data was mistakenly always included in the
animation. Now we only include frames with explicit fcTL chunks.

As per the PNG spec (third edition):
"The static image may be included as the first frame of the animation
by the presence of a single fcTL chunk before IDAT. Otherwise, the
static image is not part of the animation."

We also fall back to the IDAT data when APNG has acTL but no fcTL
chunks. Test image is 062.png from fDAT-inherits-cICP.html from WPT.
2025-05-01 10:30:00 +02:00
Mohamed amine Bounya
b77643a2e8 RequestServer: Don't assert for socket fd not being CURL_SOCKET_BAD
The assertion in `WebSocketImplCurl::did_connect()` keeps failing for
multiple websockets when loading `https://www.speedtest.net/` since
commit 14ebcd4. This fixes that by checking and returning false if
something went wrong and letting the caller function handle it.
2025-04-30 18:20:26 -06:00
Psychpsyo
82387e2127 LibWeb: Avoid changing button border color on disable/hover 2025-04-30 20:13:14 +01:00
Aliaksandr Kalenik
81b6a1100e LibJS: Skip iterator result object allocation in for..of and for..in
Introduce special instruction for `for..of` and `for..in` loop that
skips `{ value, done }` result object allocation if iterator is builtin
(array, map, set, string). This reduces GC pressure significantly and
avoids extracting the `value` and `done` properties.

This change makes this micro benchmark 48% faster on my computer:
```js
const arr = new Array(10_000_000);
let counter = 0;
for (let _ of arr) {
    counter++;
}
```
2025-04-30 20:51:39 +02:00
Aliaksandr Kalenik
ab52d86a69 LibJS: Allow advancing built-in iterators without result object creation
Expose a method on built-in iterators that allows retrieving the next
iteration result without allocating a JS::Object. This change is a
preparation for optimizing for..of and for..in loops.
2025-04-30 20:51:39 +02:00
Tim Ledbetter
c72d5943e6 LibWeb: Support interpolating translate values 2025-04-30 19:36:56 +02:00
Tim Ledbetter
27baaa13e9 LibWeb: Support parsing and serializing 3D translate values 2025-04-30 19:36:56 +02:00
Tim Ledbetter
d804f1311c LibWeb: Don't serialize scale z value if it is 1 2025-04-30 19:36:56 +02:00
Sam Atkins
094c2bbc89 LibWeb/SVG: Remove remaining user of of old try_resolve_url_to() 2025-04-30 17:38:38 +01:00
Sam Atkins
326933cd93 LibWeb/CSS: Use CSS::URL for <url> and <paint> types 2025-04-30 17:38:38 +01:00
Sam Atkins
d301510ab2 Everywhere: Correct "FIMXE" typo 2025-04-30 17:38:38 +01:00
Andrew Kaster
edfaa76c90 LibWeb: Exit the current process when event loop quits during spin_until
This is a LibWeb special. We keep running into cases where we end up
with one or more Platform or event loop spin_until() calls on the stack
after the event loop has been cancelled and the WebContent process has
been asked to exit.

To prevent too much nonsense from exiting processes early from affecting
our other, more well-behaved processes, put this special logic in the
critical path of such Web-specific event loop spins.
2025-04-30 11:12:23 -04:00
Andrew Kaster
16f72ca36c LibIPC: Don't verify that socket is closed when getting EPIPE on send
We can get an EPIPE when the other end of the connection closes, such
as when switching to a new WebContent process due to site isolation.
2025-04-30 11:12:23 -04:00
Andrew Kaster
b4f34ee860 LibWeb: Remove unnecessary VERIFY from EventLoopPlugin's deferred_invoke 2025-04-30 11:12:23 -04:00
Andrew Kaster
b50d03f42e LibCore+LibWebView: Restore was_exit_requested to EventLoop
This method was removed in e015a43b51

However, it was not exactly *unused* as the commit message would say.
This method was the only thing that allowed spin_until to exit when
the event loop was cancelled. This happens normally when IPC connections
are closed, but also when the process is killed.

The logic to properly handle process exit from event loop spins needs to
actually notify the caller that their goal condition was not met though.
That will be handled in a later commit.
2025-04-30 11:12:23 -04:00
Timothy Flynn
0cd5e99066 LibWeb: Use the correct target realm to tee a stream
We currently store Web::Fetch::Infrastructure::Response objects in the
HTTP cache. They are associated with their original realm, but when we
use a cached response, we clone it into the target realm. For example,
two <iframe> objects loading the same HTML will be in different realms.

When we clone the response, we must use the target realm throughout the
entire cloning process. We neglected to do this for the cloned response
body stream, which is cloned via teeing. The result was the the stream
for the "cloned" response was created in the original realm, causing
issues down the line when reading from that stream tried to handle read
promises on behalf of the original realm. There are protections in place
to prevent this from happening, and the cached response read would never
complete.
2025-04-30 09:30:15 -04:00
Timothy Flynn
6cc5ac8f82 LibWeb: Remove unused VM from ReadLoopReadRequest 2025-04-30 09:30:15 -04:00
Timothy Flynn
6b4b7a54de LibJS: Revert ArrayIterator and RegExpStringIterator to manual iterators
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/de62e8d

This did not actually seem to affect our implementation as we were not
using generators here to begin with. So this patch is basically just
adding spec comments.
2025-04-30 07:29:34 -04:00
Sam Atkins
107d0cafcf Tests: Disable flaky APNG test
This frequently flakes on CI.
2025-04-30 11:34:19 +01:00
Gingeh
004d1305c8 LibWeb: Don't accidentally create a layout node for display: none 2025-04-30 11:26:18 +01:00
Andreas Kling
7a600e60bc LibJS: Mark catch parameter as initialized local when applicable
Otherwise we'll emit a TDZ check for every `catch` parameter immediately
after initializing it. This check would never fail, so it's redundant.
2025-04-30 09:38:40 +02:00
Andreas Kling
00f7a6f9e0 LibJS: Remove unused bytecode VM register reservation
We were not actually using the "saved exception" register for anything,
but we were clearing it on every function entry.
2025-04-30 09:38:40 +02:00
Andrew Kaster
e5465ff8e5 LibWeb: Crash less when the main thread exits while trying to render
Attach a 'job' to the main thread event loop, trusting that the event
loop implementation will cancel it when asked to quit. This is something
that our Unix implementation does, but isn't strictly part of the
contract of EventLoopImplementation.
2025-04-29 09:51:22 -06:00
Andrew Kaster
27db7ed11f LibIPC: Guard better against closure in the TransportSocket send thread
And crash less when the socket is closed while there are still messages
in the queue.
2025-04-29 09:51:22 -06:00
rmg-x
d64e6abe08 CI+Toolchain: Remove unnecessary BuildVcpkg.sh
This script was rewritten in Python in commit:
c92d9cce42

Since it just executes the Python anyway, remove it and do that in CI
ourselves.
2025-04-29 16:34:24 +01:00
stelar7
dde80a434c LibWeb/IDB: Disable test that now hits a timeout 2025-04-29 17:06:17 +02:00
stelar7
81d7f27c73 LibWeb/IDB: Fix record checking using the wrong key comparison 2025-04-29 17:06:17 +02:00
stelar7
c81c17c0fb LibWeb/IDB: Implement IDBObjectStore::get 2025-04-29 17:06:17 +02:00
stelar7
18a008d073 LibWeb/IDB: Implement retrieve_a_value_from_an_object_store 2025-04-29 17:06:17 +02:00
stelar7
d5cf2cee41 LibWeb/IDB: Implement IDBObjectStore::count 2025-04-29 17:06:17 +02:00
stelar7
694375d3ac LibWeb/IDB: Implement count_the_records_in_a_range 2025-04-29 17:06:17 +02:00
stelar7
64d251b36c LibWeb/IDB: Implement convert_a_value_to_a_key_range 2025-04-29 17:06:17 +02:00
Andreas Kling
1f0c67cc12 Revert "LibJS: Add StackFrame to avoid indirection in VM register access"
This reverts commit 36bb2824a6.

Although this was faster on my M3 MacBook Pro, other Apple machines
disagree, including our benchmark runner. So let's revert it.
2025-04-29 16:08:42 +02:00
Jelle Raaijmakers
6176b05ca5 LibWeb: Align editing whitespace canonicalization with other browsers
The spec calls for a couple of very specific whitespace padding
techniques whenever we canonicalize whitespace during the execution of
editing commands, but it seems that other browsers have a simpler
strategy - let's adopt theirs!
2025-04-29 15:30:34 +02:00
Andreas Kling
36bb2824a6 LibJS: Add StackFrame to avoid indirection in VM register access
This is a simple trick to generate better native code for access to
registers, locals, and constants. Before this change, each access had
to first dereference the member pointer in Interpreter, and then get to
the values. Now we always have a pointer directly to the values on hand.

Here's how it looks:

    class StackFrame {
    public:
        Value get(Operand) const;
        void set(Operand, Value);

    private:
        Value m_values[];
    };

And we just place one of these as a window on top of the execution
context's array of values (registers, locals, and constants).
2025-04-29 14:23:03 +02:00
Jelle Raaijmakers
35efd4d14b LibWeb+LibGfx: Support alpha in CanvasRenderingContext2D
This is implemented by these related changes:

  * The Skia alpha type 'Opaque' is selected for surfaces that were
    created with the intention of not having an alpha channel.
    Previously we were simply creating one with alpha.

  * Clearing now happens through Skia's `clear()` which always uses the
    source color's value for the result, instead of setting all values
    to 0.

  * CanvasRenderingContext2D selects a different clearing color based on
    the `alpha` context attribute's value.
2025-04-29 13:51:23 +02:00
Jelle Raaijmakers
fac0f82031 LibWeb: Add CanvasRenderingContext2D context attribute parsing
Makes `context.getContextAttributes()` work.
2025-04-29 13:51:23 +02:00
Timothy Flynn
4d70f6ce1c LibJS: Ensure iterator parameter validation closes underlying iterator
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/9552f29
https://github.com/tc39/ecma262/commit/f2bad00
2025-04-29 07:33:08 -04:00
Timothy Flynn
908349f8fe LibJS: Add a TRY_OR_CLOSE_ITERATOR macro for IfAbruptCloseIterator
Behaves just like TRY_OR_REJECT for promises.
2025-04-29 07:33:08 -04:00
Timothy Flynn
568524f8ba LibJS: Close sync iterator when async wrapper yields rejection
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/ff129b1
2025-04-29 07:33:08 -04:00
Timothy Flynn
15faaeb2bb LibJS: Remove [[VarNames]] from GlobalEnvironment
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/ed75310
2025-04-29 07:33:08 -04:00
Timothy Flynn
9c85a16aeb LibJS: Standardize spec prose for Math.sumPrecise 2025-04-29 07:33:08 -04:00
Timothy Flynn
9674210ef8 LibJS: Update spec steps / links for the Float16Array proposal
This proposal has reached stage 4 and been merged into the main ECMA-262
spec. See:

https://github.com/tc39/ecma262/commit/d430ace
2025-04-29 07:33:08 -04:00
Timothy Flynn
adf6024805 LibJS: Update spec steps / links for the RegExp.escape proposal
This proposal has reached stage 4 and been merged into the main ECMA-262
spec. See:

https://github.com/tc39/ecma262/commit/e2da759
2025-04-29 07:33:08 -04:00
Timothy Flynn
2401764697 LibJS: Update spec steps / links for the JSON modules proposal
This proposal has reached stage 4 and been merged into the main ECMA-262
spec. See:

https://github.com/tc39/ecma262/commit/3feb1ba
2025-04-29 07:33:08 -04:00
Timothy Flynn
3867a192a1 LibJS: Update spec steps / links for the import-assertions proposal
This proposal has reached stage 4 and been merged into the main ECMA-262
spec. See:

https://github.com/tc39/ecma262/commit/4e3450e
2025-04-29 07:33:08 -04:00
Tim Ledbetter
c1a3b95176 LibWeb: Set transition property name when firing transition events 2025-04-29 12:23:31 +02:00
Gingeh
aa9f556500 LibWeb: Light dismiss dialogs on click 2025-04-28 19:41:38 -06:00
Gingeh
1f1884da54 LibWeb: Light dismiss popovers on click 2025-04-28 19:41:38 -06:00
Andreas Kling
6061da3382 LibJS: Overload Instruction::length() on variable-length instructions
This allows the DISPATCH_NEXT() macro to do the math to find the next
instruction boundary point without performing a function call.
2025-04-29 02:09:35 +02:00
Andreas Kling
a2b7e04da3 LibJS: Defer looking up the realm in ordinary_call_evaluate_body()
We don't actually need the realm for normal function calls, so we
can avoid looking it up on the EC stack in that case.
2025-04-29 02:09:35 +02:00
Andreas Kling
0f1be720bb LibJS: Mark exception path [[unlikely]] in ordinary_call_evaluate_body() 2025-04-29 02:09:35 +02:00
Andreas Kling
58925887ce LibJS: Inline VM::bytecode_interpreter() 2025-04-29 02:09:35 +02:00
Andreas Kling
35275651e3 LibJS: Skip stack overflow check in ESFO::prepare_for_ordinary_call()
We already do a stack overflow check when entering run_bytecode(),
which is the first thing that happens when we actually invoke the ESFO
executable.
2025-04-29 02:09:35 +02:00
Andreas Kling
95ba74d934 LibJS: Remove redundant VERIFY in run_executable()
Getting the running_execution_context() already verifies that the
execution context stack is non-empty, we don't need to do it separately
here as well.
2025-04-29 02:09:35 +02:00
Andreas Kling
6de1a0aeaf LibJS: Don't cache a pointer to accumulator register in run_bytecode()
The old accumulator register is really only used to pass the end
completion to the caller of run_bytecode() nowadays. As such, we don't
need to cache a pointer to it for fast access. One less thing to do
on run_bytecode() entry.
2025-04-29 02:09:35 +02:00
Andreas Kling
942ce2162d LibJS: Mark stack overflow path in run_bytecode() [[unlikely]] 2025-04-29 02:09:35 +02:00
Hikmat Jafarli
bd9d489370 LibWeb: Re-evaluate the style block when the type attribute changes 2025-04-29 01:01:02 +02:00
Andreas Kling
4d17707b26 LibJS: Store bytecode VM program counter in ExecutionContext
This way it's always automatically correct, and we don't have to
manually flush it in push_execution_context().

~7% speedup on the MicroBench/call* tests :^)
2025-04-28 21:12:48 +02:00
Tim Ledbetter
e7ae9c8ebf LibWeb: Parse all as keyword in transition shorthand
This ensures that the parsing of the `transition` shorthand property
behaves in the same way as the `transition-property` longhand.4
2025-04-28 20:51:36 +02:00
teaalltr
a3e485e2d0 LibWeb: Add fast_is for span and div 2025-04-28 19:46:05 +01:00
Shannon Booth
23f3ecbe98 AK: Don't iterate through entire String for String::ends_with 2025-04-28 10:50:31 -04:00
Andreas Kling
233097c250 LibJS: Inline part of VM::run_queued_promise_jobs()
Most of the time there are no queued promise jobs to run after exiting
a stack frame. By moving the check inline, leaving a function call gets
a measurable speedup in the common case.
2025-04-28 10:39:42 -04:00
Andreas Kling
b4554c01db LibJS: Mark ESFO path for [[Call]] on a class constructor [[unlikely]]
This is an exception path that's not supposed to be called normally,
so let's mark it unlikely.
2025-04-28 10:39:42 -04:00
Andreas Kling
6ec4d0f5ba LibJS: Mark stack overflow exception code path as [[unlikely]]
This is supposed to be exceedingly rare, so a great candidate for
[[unlikely]] annotation.
2025-04-28 10:39:42 -04:00
Andreas Kling
580b892b9e AK: Demote VERIFY in NonnullRefPtr to ASSERT
NonnullRefPtr almost always has a non-null pointer internally, that's
what the class is for, after all! The one edge case where it has null
internally is after you move() it. But it's always a bug to use an
NNRP after moving from it, and we have clang-tidy yelling at us if
that ever happens.

Demoting this removes a gazillion overly paranoid null checks.
2025-04-28 10:39:42 -04:00
Andreas Kling
074ca5d5b4 LibJS: Make ESFO::ordinary_call_evaluate_body() return TCO<Value>
This matches what the caller wants to return and allows us to simplify
a bunch of logic around returning a value or throwing.
2025-04-28 12:44:49 +02:00
Andreas Kling
670e439e1e LibJS: Put FLATTEN on ECMAScriptFunctionObject.[[Call]]
This makes function calls ~5% faster in micro-benchmarks on my MBP.
Basically free money on the table. Let's take it!
2025-04-28 12:44:49 +02:00
Andreas Kling
d0d87d3aed LibJS: Demote some overly paranoid VERIFY()s in ESFO [[Call]] flow 2025-04-28 12:44:49 +02:00
Andreas Kling
403ae86fd9 LibJS: Pass VM& to ECMAScriptFunctionObject [[Call]] helpers
This avoids fetching the VM from the Cell::private_data() repeatedly.
2025-04-28 12:44:49 +02:00
Shannon Booth
8a3c66d8a6 LibWeb: Make a bunch of CSP classes not realm associated
These are not associated with a javascript realm, so to avoid
confusion about which realm these need to be created in, make
all of these objects a GC::Cell, and deal with the fallout.
2025-04-28 12:41:28 +02:00
Tim Ledbetter
04fde1c550 LibWeb: Ensure lang pseudoclass matches multiple segment subcodes 2025-04-28 11:29:30 +01:00
Tim Ledbetter
74c803c87b LibWeb: Ensure |= value selector handles multiple segments correctly
Previously, the `|=` would not compare strings containing `-`
characters correctly because it would only compare the element
attribute up to the first `-` character.
2025-04-28 11:29:30 +01:00
devgianlu
1c3d849b8b LibCrypto: Remove unused big numbers modular functions
Remove `Mod`, `ModularInverse`, `ModularPower` and `LCM` as
they are unused.
2025-04-28 12:05:26 +02:00
devgianlu
5f1a30197c LibCrypto: Remove the concept of invalid big integers
This concept is rarely used in codebase and very much error-prone
if you forget to check it.

Instead, make it so that operations that would produce invalid integers
return an error instead.
2025-04-28 12:05:26 +02:00
devgianlu
14387e5411 LibCrypto: Remove unused big numbers random and primality functions
Remove `random_number`, `is_probably_prime` and `random_big_prime` as
they are unused.
2025-04-28 12:05:26 +02:00
devgianlu
dd0cced92f LibJS: Prevent huge memory allocations for bigint left shift 2025-04-28 12:05:26 +02:00
devgianlu
51a2fb3ffc LibCrypto: Add Fibonacci signed and unsigned bigint benchmarks 2025-04-28 12:05:26 +02:00
devgianlu
ce98d2bbf3 LibCrypto: Check ECPrivateKey version when parsing
The version should always be one for version one. Fail if it isn't.
2025-04-28 12:05:26 +02:00
devgianlu
a019efb24b LibCrypto+LibJS: Remove {Signed,Unsigned}BigInteger to_base_deprecated
Use `to_base` instead.
2025-04-28 12:05:26 +02:00
devgianlu
ac16008d09 LibCrypto: Remove unused create_invalid method on UnsignedBigInteger 2025-04-28 12:05:26 +02:00
Tim Ledbetter
f854f644a7 LibWeb: Don't crash when interpolating non <number> scale values 2025-04-28 11:46:34 +02:00
stelar7
edf64b801c LibWeb/IDB: Add store to the current transaction when created 2025-04-28 11:31:31 +02:00
stelar7
47d6b568fd LibWeb/IDB: Dont keep trailing separator when splitting key paths 2025-04-28 11:31:31 +02:00
stelar7
577f799240 LibWeb/IDB: Fix a bug where the KeyGenerator was not incremented 2025-04-28 11:31:31 +02:00
stelar7
facfcd87c2 LibWeb/IDB: Introduce an Invalid KeyType
This cleans up the code around failure/invalid/exception a bit
2025-04-28 11:31:31 +02:00
stelar7
61384473ca LibWeb/IDB: Implement IDBDatabase::transaction() 2025-04-28 11:31:31 +02:00
Andreas Kling
a05be67e4a LibJS: Let invokers (callers) of [[Call]] allocate ExecutionContext
Instead of letting every [[Call]] implementation allocate an
ExecutionContext, we now make that a responsibility of the caller.

The main point of this exercise is to allow the Call instruction
to write function arguments directly into the callee ExecutionContext
instead of copying them later.

This makes function calls significantly faster:
- 10-20% faster on micro-benchmarks (depending on argument count)
- 4% speedup on Kraken
- 2% speedup on Octane
- 5% speedup on JetStream
2025-04-28 01:23:56 +02:00
Andreas Kling
93788f8057 LibJS: Add parentheses to ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK()
Just to stop clang-tidy from complaining about it every time.
2025-04-28 01:23:56 +02:00
Andreas Kling
373307db5b LibJS: Mark arguments local as initialized after creating it
This avoids emitting an unnecessary TDZ check for the first time we
access the arguments object.
2025-04-28 01:23:56 +02:00
Shannon Booth
9e44d86915 LibJS: Remove value_or from JS::Value
This is no longer used after 3cf5053.
2025-04-27 11:14:54 -04:00
Shannon Booth
420949b134 LibWeb/HTML: Make Navigation navigate event trusted
Fixes WPT test:

https://wpt.live/navigation-api/navigate-event/signal-abort-intercept.html
2025-04-27 07:54:02 -04:00
Shannon Booth
6032827fe7 LibWeb/HTML: Inform navigation API about frame container destruction 2025-04-27 07:54:02 -04:00
Ali Mohammad Pur
022cd1adca LibRegex: Use the right offset when patching jumps through fork-trees
Fixes #4474.
2025-04-27 12:16:15 +02:00
Tim Ledbetter
8a398e7a88 LibWeb: Parse all transition-property value as keyword
We were previously parsing this value, as a custom-ident, meaning that
the code path for handling the `all` case wasn't being followed.
2025-04-27 09:49:00 +01:00
Timothy Flynn
ac1c2a956a LibWeb: Implement caching of reflected element array attributes
For attributes like Element.ariaControlsElements, which are a reflection
of FrozenArray<Element>, we must return the same JS::Array object every
time the attribute is invoked - until its contents have changed. This
patch implements caching of the reflected array in accordance with the
spec.
2025-04-26 17:29:38 -04:00
Timothy Flynn
6f894ccd77 Meta: Remove -Wno-overloaded-virtual from clang compilation
This silenced warning was added a long time ago when we were first
bringing up Lagom: a619943001

The commit message indicates we were seeing errors due to this warning
in many places. We now compile just fine with this warning enabled, so
let's remove its silencer to be a little more consistent between clang
and GCC.
2025-04-26 09:04:45 -06:00
Timothy Flynn
317cf65eb0 LibJS: Avoid naming conflict between Object's and Error's is_error
Object defines an is_error virtual method to be overridden by Error for
fast-is. This is the same name as the Error.isError constructor method.
Rename the former to avoid conflicts, as GCC 15 just started warning on
this.
2025-04-26 09:04:45 -06:00
Shannon Booth
6d622a6c04 LibWeb/DOM: Use as_if<T> in a bunch more places in DOM::Node 2025-04-26 08:45:37 -06:00
Shannon Booth
31a3bc3681 LibWeb: Implement 'State-preserving atomic move integration'
This was recently added to both the HTML and DOM specifications,
introducing the new moveBefore DOM API, as well as the new internal
'removing steps'.

See:

 * https://github.com/whatwg/html/commit/432e8fb
 * https://github.com/whatwg/dom/commit/eaf2ac7
2025-04-26 08:45:37 -06:00
Shannon Booth
a47c4dbc63 LibWeb/DOM: Factor out 'live range pre remove steps' AO
This was a refactoring made in the DOM spec as part of the
introduction of the move before API.
2025-04-26 08:45:37 -06:00
Timothy Flynn
0e2036d6c2 LibWeb: Temporarily disable site isolation for subframes
We don't yet support out-of-process subframes. Explicitly disable even
attempting to isolate subframes. Otherwise, navigating a subframe to a
non-same-site URL would actually cause the top-level frame to navigate
with our current implementation.
2025-04-26 10:15:47 -04:00
Timothy Flynn
e52c09ad4c LibWeb: Avoid copying a URL needlessly during subframe navigation
Noticed a clangd warning for this while looking at a subframe site
isolation issue.
2025-04-26 10:15:47 -04:00
Aliaksandr Kalenik
2d732b2251 LibJS: Skip allocating locals for arguments that allowed to be local
This allows us to get rid of instructions that move arguments to locals
and allocate smaller JS::Value vector in ExecutionContext by reusing
slots that were already allocated for arguments.

With this change for following function:
```js
function f(x, y) {
    return x + y;
}
```

we now produce following bytecode:
```
[   0]    0: Add dst:reg6, lhs:arg0, rhs:arg1
[  10]       Return value:reg6
```

instead of:
```
[   0]    0: GetArgument 0, dst:x~1
[  10]       GetArgument 1, dst:y~0
[  20]       Add dst:reg6, lhs:x~1, rhs:y~0
[  30]       Return value:reg6
```
2025-04-26 11:02:29 +02:00
Aliaksandr Kalenik
3f04d18ef7 LibJS: Add new operand type for function arguments
This allows us to directly access passed arguments instead of copying
them to register/local first using GetArgument instruction.
2025-04-26 11:02:29 +02:00
Aliaksandr Kalenik
81a3bfd492 LibJS: Allow using locals if arguments is used in strict mode
Previously we blocked using locals for function arguments whenever
`arguments` was mentioned in function body, however, this is not
necessary in strict mode, where mutations to the arguments object are
not reflected in the function arguments and vice versa.
2025-04-25 21:08:24 +02:00
Andreas Kling
d8ea16d94e LibWeb: Don't assume calc() simplification worked on invalid tree
Fixes #4469
2025-04-25 16:55:05 +02:00
Timothy Flynn
4e298db4f5 LibWeb: Update FIXMEs about FrozenArray with more up-to-date description
We could support FrozenArray pretty easily here, but we would regress on
SameObject handling.
2025-04-25 16:43:43 +02:00
Timothy Flynn
ad34fdad48 LibWeb: Convert trivial attributes to FrozenArray 2025-04-25 16:43:43 +02:00
Timothy Flynn
62167d923c LibWeb: Convert ARIA attributes to FrozenArray 2025-04-25 16:43:43 +02:00
Timothy Flynn
98f73a6b31 LibWeb: Implement FrozenArray IDL attributes
A FrozenArray is simply a sequence whose integrity level is "frozen".
2025-04-25 16:43:43 +02:00
Andreas Kling
cf704cfbfc LibWeb: Implement interpolation for CSS scale values
And let's handle the 3rd (Z) scale parameter as well, while we're here.

At least 242 new passes on WPT.
2025-04-25 14:08:12 +02:00
Andreas Kling
4f4b43f1d2 Tests: Import WPT test for CSS scale interpolation 2025-04-25 14:08:12 +02:00
Shannon Booth
a2cca59516 LibWeb+LibWebView+Services: Add IPC for starting WebWorker of a type
The provides some of the plumbing for a WebContent process to spin
up a WebWorker that is not just a dedicated worker.
2025-04-25 14:07:51 +02:00
Shannon Booth
041ff0c7ff LibWeb/HTML: Hook up a WorkerAgent for web workers 2025-04-25 14:07:51 +02:00
Shannon Booth
5290ebfe19 LibJS: Switch Agent [[CanBlock]] slot to a enum member
It turns out it was a mistake to make this a virtual since
ServiceWorkerAgents are effectively the exact same as
DedicatedWorkerAgents and SharedWorkerAgents just with [[CanBlock]]
set to false.
2025-04-25 14:07:51 +02:00
Shannon Booth
7dd7e5b438 LibJS+LibWeb: Defer initialization of the Agent after VM constructor
This helps unwind a niggly depedency where the VM owns and constructs
the Heap and the Agent. But the agent wants to have customized
construction that depends on the heap. Solve this by defering
the initialization of the Agent to after we have constructed the
VM and the heap.
2025-04-25 14:07:51 +02:00
Shannon Booth
8263a9863f LibJS+LibWeb: Do not return error from VM::create
This never returns an error to propogate, also allowing ErrorOr
to be removed from creating the main thread VM.
2025-04-25 14:07:51 +02:00
Shannon Booth
084cceab5c LibWeb: Split out SimilarOriginWindowAgent from HTML::Agent
To allow for adding the concept of a WorkerAgent to be reused
between shared and dedicated workers. An event loop is the
commonality between the different agent types, though, there
are some differences between those event loops which we customize
on the construction of the HTML::EventLoop.
2025-04-25 14:07:51 +02:00
Shannon Booth
939bb10828 LibWeb/HTML: Rename WorkerAgent to WorkerAgentParent
This is to differentiate the agent representation for the parent
process for the WorkerAgent in the child process which is actually
hooked up to the javascript VM.

I am not sure if this is a good name, but I can't really think of
anything better which is consistent with the names used by the rest
of the codebase.
2025-04-25 14:07:51 +02:00
Jelle Raaijmakers
2fc1cafb8a LibWeb: Exclude fixed positioned boxes from scrollable overflow
Sometimes fixed positioned boxes would extend the viewport's scrollable
overflow, which according to the spec should never happen. There are
some nuances to this, such as properly determining the fixed positioning
containing block for a fixed position box, but for now this prevents
some pages from being overly scrollable.

Fixes horizontal scrollability of https://tweakers.net.
2025-04-25 14:07:38 +02:00
stelar7
5ae069a031 LibWeb/IDB: Use correct state to check for throw condition 2025-04-25 07:23:41 -04:00
stelar7
d28a4434d0 LibWeb/IDB: Dont include databases with version 0 in databases() 2025-04-25 07:23:41 -04:00
Shannon Booth
8ac096c0e2 LibWeb/HTML: Fix parsing of protocol in Location.protocol setter
This never worked properly when implemented as it would always
throw an error for an invalid scheme on URL parsing.

Fixes at least some tests in:

https://wpt.live/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html

And all tests in:

https://wpt.live/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html

And maybe tests in some other places too, but these are not imported
as the tests are written with delays that makes them take a long time
to run, and some of them rely on HTTP(s).
2025-04-25 07:21:02 -04:00
Shannon Booth
3bb36d9379 LibWeb/ServiceWorker: Implement ServiceWorkerGlobalScope event handlers 2025-04-25 11:02:53 +02:00
Shannon Booth
50b7e0807d LibWeb/ServiceWorker: Add ServiceWorker event names 2025-04-25 11:02:53 +02:00
Andreas Kling
27efb3b140 LibWeb: When declarative shadow attachment fails, continue in right spot
If attachment fails for whatever reason (e.g the host element is not
allowed to be a host), the HTML spec tells us to insert the template
element anyway and proceed.

Before this change, we were recomputing the insertion location at this
point, which caused it to be *inside* the template element. Inserting
the template element into itself didn't work, and so the DOM would end
up incorrect.

The fix here is to simply use the insertion point we determined earlier
in the same function, before putting a template element on the stack of
open elements. We already do this elsewhere.

Fixes at least 228 subtests on WPT. :^)
2025-04-25 11:01:17 +02:00
Andreas Kling
1102a31866 LibWeb: Improve DOM dump formatting for HTML template elements
Let's dump both the template contents, and any DOM nodes inside the
template element itself, since both are valid states produced by the
HTML parser.
2025-04-25 11:01:17 +02:00
Andreas Kling
43eea9212d Tests: Import comprehensive WPT test for declarative shadow attachment 2025-04-25 11:01:17 +02:00
Andreas Kling
10cff06a95 LibWeb: Move presentation attrs from SVGGraphicsElement to SVGElement
This matches how other browser behave and fixes a bunch of WPT tests.
2025-04-25 10:18:34 +02:00
Timothy Flynn
fe6d8131ae LibWeb: Return correct type from CSSNestedDeclarations::style
We implement CSSStyleProperties so let's use it.
2025-04-25 08:48:29 +02:00
Timothy Flynn
13ac6c4fde LibWeb: Implement ariaActiveDescendantElement spiritually closer to spec
We are meant to store a weak reference to the element indicated by this
attribute, rather than a GC-protected strong reference. This also hoists
the "get the attr-associated element" AO into its own function, rather
than being hidden in IDL, to match "get the attr-associated elements".
2025-04-25 01:20:12 +01:00
Timothy Flynn
f985ac8884 LibWeb: Implement element-referencing ARIA attributes
There are ARIA attributes, e.g. ariaControlsElements, which refer to a
list of elements by their ID. For example:

    <div aria-controls="item1 item2">

The div.ariaControlsElements attribute would be a list of elements whose
ID matches the values in the aria-controls attribute.
2025-04-25 01:20:12 +01:00
Timothy Flynn
0289df9357 LibWeb: Move ariaActiveDescendantElement to ARIAMixin
Not an issue right now, but all IDL types that include the ARIA mixin
will need this.
2025-04-25 01:20:12 +01:00
Timothy Flynn
a7b1f2c800 LibWeb: Make ARIAMixin::to_element return a reference
Let's avoid confusion on whether this method can return null. It can't.
This also adds a non-const override, as that will be needed soon.
2025-04-25 01:20:12 +01:00
Timothy Flynn
88b41d4d76 LibWeb: Re-import shadow DOM property reflection tests
The property-reflection.html test was partially split into a second file
recently, property-reflection-imperative-setup.html. Let's re-import to
ensure we have the latest. See:

https://github.com/web-platform-tests/wpt/commit/2518df1
2025-04-25 01:20:12 +01:00
Andrew Kaster
6eb0e9ab38 CI: Use a raw actions/cache step for vcpkg instead of the x-gha source
This is a workaround for the deprecation of the cache v1 REST API that
was replaced with a new protobuf RPC based API this month. vcpkg was
using the private cache backend API without the knowledge of the GitHub
actions team, and was thus broken by the deprecation.

While we wait for Microsoft to talk to Microsoft to get this feature
restored, we can use the raw actions/cache step to get almost the same
cache behavior. The only difference is that the cache will be less fine
grained than the per-package cache that VCPKG_BINARY_SOURCES of x-gha
was giving us before.
2025-04-24 17:40:39 -06:00
Andreas Kling
0553bcb35b LibWeb: Simplify standalone CSS math functions when used outside calc()
Math functions like abs(), clamp(), round(), etc, can be used by
themselves in property values, without wrapping them in calc().

Before this change, we were neglecting to run calc simplification on the
generated calculation node trees. By doing that manually after parsing a
standalone math function, we score at least a couple hundred WPT points.
2025-04-24 20:38:00 +02:00
Jelle Raaijmakers
94ae63c436 LibWeb: Wrap inline children without utilizing a Vector
No functional changes.
2025-04-24 19:12:50 +02:00
Jelle Raaijmakers
6f800caeaa LibWeb: Don't mess up the order of nodes when wrapping inline contents
Whenever we introduce a block element in a container that at that point
has only had inline children, we create an anonymous wrapper for all the
inline elements so we can keep the invariant that each container
contains either inline or non-inline children. For some reason, we
ignore all the out-of-flow nodes since they are layed out separately and
it was thought that this shouldn't matter.

However, if we are dealing with inline blocks and floating blocks, the
order of the inline contents _including_ out-of-flow nodes becomes very
important: floating blocks need to take the order of nodes into account
when positioning themselves.

Fix this by simply hoisting the out-of-flow nodes into the anonymous
wrapper as well.

Fixes the order of blocks in #4212. The gap is still not present.
2025-04-24 19:12:50 +02:00
Andreas Kling
d33445a4ea LibWeb: Notify ObservableArray observer about deletions in clear()
Another +1 WPT subtest!
2025-04-24 18:26:54 +02:00
Andreas Kling
cf34a7bb32 LibWeb: Invalidate owner sheet on add/remove in CSSStyleProperties
Fixes at least 2 WPT subtests.
2025-04-24 18:26:54 +02:00
Andreas Kling
fbb3b06462 LibWeb: Don't assume table caption box wants to create a BFC
Instead, use the generic create_independent_formatting_context_if_needed
so that unusual situations like image-as-table-caption don't crash.

This logic clearly needs more work, but let's at least do better than
crashing. This gives us 26 new subtest passes on WPT.
2025-04-24 18:26:54 +02:00
Andreas Kling
f7a7cd9b2b LibWeb: Prevent infinite recursion on abspos w/ intrinsic max-size
We were incorrectly deciding that abspos elements shouldn't treat many
max-width and max-height values as `none`. My best understanding is that
this was a hack in 2023 for an issue that has been solved since then.

By removing the incorrect short-circuit, we stop at least one WPT test
from crashing due to infinite recursion and get ourselves +34 passes.
2025-04-24 18:26:54 +02:00
Andreas Kling
e5d62e9915 LibWeb: Track whether HTMLLinkElement was enabled when created by parser
This information is needed by the script-blocking style sheet logic, and
its absence was causing a WPT test to crash.
2025-04-24 18:26:54 +02:00
Andreas Kling
1772adb600 LibWeb: Don't crash on non-finite values in CSS clamp() function
Stops a WPT test from crashing, giving us 29 new subtest passes. :^)
2025-04-24 18:26:54 +02:00
Andreas Kling
2f76b24b89 LibWeb: Throw on deleting CSS @namespace rule in disallowed conditions
Fixes one(!) WPT test :^)
2025-04-24 18:26:54 +02:00
aplefull
223c9c91e6 LibJS: Implement rawJSON and isRawJSON functions 2025-04-24 09:33:49 -04:00
aplefull
e0ceb66580 LibGfx: Fix incorrect colors in ICO-embedded BMPs 2025-04-24 13:46:54 +01:00
Andrew Kaster
9bae24cc4a LibJS: Add and use ValidateNonRevokedProxy AO
This refactor is from two editorial changes to the spec from a while
back.

44d1cae2b2
21ffeee869
2025-04-24 10:37:39 +02:00
Aliaksandr Kalenik
e48645c83f LibJS: Cache arguments span in ExecutionContext
Allows us to avoid doing math in ExecutionContext::argument()
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
ff751173ac LibJS: Delete unused m_arguments member in Interpreter 2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
a329868c1b LibJS: Allocate ExecutionContext memory using alloca() when possible
This should be faster than heap allocation. However, heap allocation is
still necessary in some cases, such as with generators and async
functions.
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
5a92929282 LibJS: Put vector of regs+consts+locals+args in tail of ExecutionContext
By doing that we avoid doing separate allocation for each such vector,
which was really expensive on js heavy websites. For example this change
helps to get EC allocation down from ~17% to ~2% on Google Maps. This
comes at cost of adding extra complexity to custom execution context
allocator, because EC no longer has fixed size and we need to maintain
a list of buckets.
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
c6cd03d7ca LibJS+LibWeb: Join arguments into vector of registers+constants+locals
This is better because:
- Better data locality
- Allocate vector for registers+constants+locals+arguments in one go
  instead of allocating two vectors separately
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
cd9e491742 AK: Use TypedTransfer in Span::overwrite()
Using `__builtin_memmove` was unsafe if items in source buffer are not
trivially copyable.
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
005551b530 AK: Fix out of bound access check in Span::overwrite()
Previously `data_size` (in bytes) was mistakenly compared with `size()`
that returns number of elements in a span.
2025-04-24 10:30:52 +02:00
Aliaksandr Kalenik
80a8040794 LibJS+LibWeb: Calculate count of regs+consts+locals before EC allocation
This is a preparation step before joining arguments vector into vector
of registers+constants+locals.
2025-04-24 10:30:52 +02:00
Ali Mohammad Pur
fca1d33fec LibRegex: Correctly calculate the target for Repeat in table alts
Fixes a bunch of websites breaking because we now verify jump offsets by
trying to remove 0-offset jumps.
This has been broken for a good while, it was just rare to see Repeat
inside alternatives that lended themselves well to tree alts.
2025-04-24 01:17:27 -06:00
Aliaksandr Kalenik
8f20899533 LibGfx: Make Bitmap atomic ref-counted
Fixes race condition when rendering thread runs destructor for
Gfx::Bitmap owned by PaintingSurface, which was not thread-safe.
2025-04-24 03:12:19 +02:00
Timothy Flynn
234c07adc9 LibWebView: Split about:settings into modules
The about:settings page has gotten beefy enough that it is a bit of a
paint to manage in a single HTML file. This patch breaks the settings
into several modules to make this page easier to mantain.

Modules have some nice benefits over classic scripts, such as enabling
strict mode by default, and allowing each module to function without
polluting the global object.
2025-04-23 19:58:58 -04:00
Timothy Flynn
6a6c56aabe LibWebView: Create a dedicated settings observer for the Application
We had a bit of an awkward setup where we want the Application to be a
SettingsObserver, but neither the Settings object nor the Application
itself was fully initialized by the time the observer was created. So
we invented a deferred observer initializer specifically for the
Application.

Instead, let's just create a dedicated observer subclass that is owned
by the Application. We can then create it once we have the singleton
Application appropriately set up.
2025-04-23 19:58:58 -04:00
Timothy Flynn
6539c72e7e LibWeb: Allow CORS requests from opaque origins to resource:// URLs
JavaScript module requests (in a non-worker context) always have CORS
enabled. However, CORS requests are only allowed for same-origin or
HTTP/S requests. This patch extends this to allow resource:// requests
from opaque origins (e.g. about: URLs).

We must also set the Access-Control-Allow-Origin header to "null" to
ensure that the response is accepted by the CORS checks. This does not
affect requesting resource:// URLs from resource:// URLs as those are
same-origin and skip CORS checks.

This ultimately enables requesting resource:// JS modules from the
about:settings page.
2025-04-23 19:58:58 -04:00
Timothy Flynn
5f9b1d3cd4 LibWeb: Make the main fetch response callback a bit easier to read
Each `if` branch in this callback returns a value, so let's add a bit of
whitespace between them to be easier on the eyes.
2025-04-23 19:58:58 -04:00
Andreas Kling
26c48c16aa LibWeb: Remove broken anonymous table wrapper layout invalidation
The special case for anonymous table wrappers actually ended up hurting
correctness by preventing the full ancestor chain from being marked for
for intrinsic size cache invalidation.

Caused Layout/input/table/propagate-style-update-to-wrapper.html to
flake on CI, and was easy to reproduce locally with sanitizers.

The fix here is simply to remove the special handling of anonymous table
wrapper parents, since *all* parents are invalidated automatically
anyway!

Began flaking in fa9c463ffd.
2025-04-23 19:43:34 -04:00
Tim Ledbetter
fc1026984c LibWeb: Don't crash when processing a transition with value none 2025-04-24 00:00:23 +02:00
Ali Mohammad Pur
4b9abdb963 LibRegex: Remove useless jumps (Jump* +0) before running opts
This leads to some more significant performance increases on the simple
/<script|<style|<link/ regex in speedometer (~2x)
2025-04-23 22:57:49 +02:00
Ali Mohammad Pur
ec0836c9ea LibRegex: Don't blindly treat multi-target tree jumps as a single jump
The tree generation was broken, we just didn't notice it because it was
very rarely being picked for more complex bytecodes.
2025-04-23 22:57:49 +02:00
Ali Mohammad Pur
09eb28ee1d LibRegex: Better estimate the cost of laying out alts as a chain
Previously we were counting the total number of *nodes* in the tree for
the chain cost, which greatly underestimated its cost when large
bytecode entries were present,
This commit switches to estimating it using the total bytecode *size*,
which is a closer value to the true cost than the tree node count.

This corresponds to a ~4x perf improvement on /<script|<style|<link/ in
speedometer.
2025-04-23 22:57:49 +02:00
Tim Ledbetter
64577ad704 LibWeb: Allow multiple values for the transition-duration property 2025-04-23 21:02:59 +01:00
Tim Ledbetter
1ca9f2a44d LibWeb: Allow multiple values for the transition-delay property 2025-04-23 21:02:59 +01:00
Tim Ledbetter
c5f1f36119 LibWeb: Allow multiple values for transition-timing-function property 2025-04-23 21:02:59 +01:00
Tim Ledbetter
7a391f419a LibWeb: Handle single value properties when normalizing transition lists
Previously, if a transition property was not wrapped in a list, it
would be replaced with the default value in
`StyleComputer::compute_transitioned_properties`.
2025-04-23 21:02:59 +01:00
Tim Ledbetter
1f8f3804a3 LibWeb: Allow transition-property with multiple values 2025-04-23 21:02:59 +01:00
stelar7
5d48652890 LibWeb/IDB: Implement IDBObjectStore::put 2025-04-23 12:31:14 -06:00
stelar7
ca1e94f9ea LibWeb/IDB: Implement IDBObjectStore::add 2025-04-23 12:31:14 -06:00
stelar7
a06cec7a3c LibWeb/IDB: Implement IDBObjectStore::add_or_put 2025-04-23 12:31:14 -06:00
stelar7
fb17dae42b LibWeb/IDB: Implement store_a_record_into_an_object_store 2025-04-23 12:31:14 -06:00
stelar7
afe7951af4 LibWeb/IDB: Implement delete_records_from_an_object_store 2025-04-23 12:31:14 -06:00
stelar7
7fa3bd00b5 LibWeb/IDB: Implement inject_a_key_into_a_value_using_a_key_path 2025-04-23 12:31:14 -06:00
stelar7
1bdf519b60 LibWeb/IDB: Implement possibly_update_the_key_generator 2025-04-23 12:31:14 -06:00
stelar7
dbe0db0cab LibWeb/IDB: Implement generate_a_key 2025-04-23 12:31:14 -06:00
stelar7
f8b09148be LibWeb/IDB: Implement asynchronously_execute_a_request 2025-04-23 12:31:14 -06:00
stelar7
551969de30 LibWeb/IDB: Implement more of IDBCursor 2025-04-23 12:31:14 -06:00
stelar7
abb11a26a8 LibWeb/IDB: Implement fire_a_success_event 2025-04-23 12:31:14 -06:00
stelar7
5c814e1a62 LibWeb/IDB: Implement fire_an_error_event 2025-04-23 12:31:14 -06:00
stelar7
d801d25c82 LibWeb/IDB: Change return type of IDBRequest::error() 2025-04-23 12:31:14 -06:00
stelar7
1d97b0d18e LibWeb/IDB: Implement check_that_a_key_could_be_injected_into_a_value 2025-04-23 12:31:14 -06:00
stelar7
eab7a2bb05 LibWeb/IDB: Implement extract_a_key_from_a_value_using_a_key_path 2025-04-23 12:31:14 -06:00
stelar7
84ea78eb4d LibWeb/IDB: Implement evaluate_key_path_on_a_value 2025-04-23 12:31:14 -06:00
stelar7
f36c4d88ff LibWeb/IDB: Implement convert_a_value_to_a_multi_entry_key 2025-04-23 12:31:14 -06:00
stelar7
8bfbcf6d9b LibWeb/IDB: Adjust return type of convert_a_value_to_a_key 2025-04-23 12:31:14 -06:00
stelar7
499548c3d0 LibWeb/IDB: Implement clone_in_realm 2025-04-23 12:31:14 -06:00
Ali Mohammad Pur
eea81738cd AK+Everywhere: Recognise that surrogates in utf16 aren't all that common
For the slight cost of counting code points when converting between
encodings and a teeny bit of memory, this commit adds a fast path for
all-happy utf-16 substrings and code point operations.

This seems to be a significant chunk of time spent in many regex
benchmarks.
2025-04-23 07:56:02 -06:00
Andrew Kaster
86c756a589 LibWeb: Import WebAssembly jsapi cross-realm torture tests from WPT
The failures here are due to us not actually implementing the
error types yet.
2025-04-23 14:09:09 +02:00
Andrew Kaster
7b0c2da14f LibWeb: Account for LegacyNamespace attribute in constructor generator
When playing games with cross-realm construction, we need to make sure
that any calls to ensure_web_prototype for LegacyNamespace objects use
the correctly namespaced prototype name.
2025-04-23 14:09:09 +02:00
Jelle Raaijmakers
79352ad725 LibWeb: Remove application of vertical float clearance to BFC Y offset
In 15103d172c we applied any remaining vertical float clearance to the
BFC's current Y offset for the next block to layout, because a `<br
style="clear: left">` could introduce clearance that would otherwise be
ignored. However, a `<div>` that floats _and_ clears `right` also
introduces this clearance and it is obvious that this should not push
down any subsequent blocks to layout in the current BFC.

Turns out, we don't need this change anymore. Some other later change
also fixed the underlying issue, and by getting rid of the original fix
we can now render https://en.wikipedia.org/wiki/SerenityOS correctly
again.

Fixes #4418.
2025-04-23 13:24:58 +02:00
Jelle Raaijmakers
1731389bfe LibWeb: Return early in clear_floating_boxes()
Get rid of an indentation level. No functional changes.
2025-04-23 13:24:58 +02:00
Jelle Raaijmakers
47ed39a790 LibWeb: Reuse floating box' margin box rect for clear: ...
We already store the resulting margin box rect for floating boxes
relative to their root coordinate space, so don't calculate them again.
No functional changes.
2025-04-23 13:24:58 +02:00
Timothy Flynn
8417ade552 LibWeb: Update the media display when the hovered component changes
This allows the media paintable to be redrawn when the media element is
paused. We change the color of some components on hover, but if the
media was paused, that would not be rendered. This wasn't an issue while
the media is playing because the update to the timeline would take care
of redrawing the paintable.
2025-04-23 13:22:56 +02:00
Timothy Flynn
7b0e62cae7 LibWeb: Use branded colors for the painted media controls 2025-04-23 13:22:56 +02:00
Timothy Flynn
094e00caef LibGfx: Add a helper to create Ladybird-branded colors 2025-04-23 13:22:56 +02:00
Sam Atkins
658569b533 LibWeb/CSS: Use CSSRule's context to parse new child rules
Keep track of which CSSRule owns a CSSRuleList, and then use that to
produce a stack of RuleContexts for the CSS Parser to use.

There are certainly other places we should do this!
2025-04-23 10:55:45 +01:00
Sam Atkins
763b1b0ee2 LibWeb/CSS: Move RuleContext type out of Parser.h
This was previously internal to the Parser, but we'd like to pass it in
from outside.
2025-04-23 10:55:45 +01:00
Sam Atkins
9465492edf LibWeb/CSS: Combine the CSSRuleList constructors 2025-04-23 10:55:45 +01:00
Sam Atkins
3d1665cc80 LibWeb/CSS: Parse nested declarations in insert_a_css_rule()
The spec algorithm changed at some point to support nested declarations,
but I only just noticed. The subtest regression is one we were passing
incorrectly.
2025-04-23 10:55:45 +01:00
Sam Atkins
fa8bbfa6a5 LibWeb/CSS: Align declaration block parsing with the spec
We have two different code paths that implement the "parse a CSS
declaration block" algorithm, for properties and descriptors. COmbining
them isn't straightforward, and doesn't seem especially useful.
2025-04-23 10:55:45 +01:00
Tim Ledbetter
8a20899382 LibWeb: Canonicalize color space when parsing color-mix() function
This amounts to replacing the "xyz" color space with "xyz-d65".
2025-04-23 11:26:27 +02:00
Gingeh
7b8af4d84c LibWeb: Remove a popover AD-HOC comment after spec update
See https://github.com/whatwg/html/pull/11197
2025-04-23 10:13:29 +01:00
Tim Ledbetter
04d7228c51 LibWeb: Implement interpolation of repeatable lists 2025-04-23 09:13:45 +01:00
Tim Ledbetter
0beb22f19e LibWeb: Implement interpolation of edge values 2025-04-23 09:13:45 +01:00
Tim Ledbetter
31dea89fe0 AK: Add lowest common multiple and greatest common divisor functions 2025-04-23 09:13:45 +01:00
Tim Ledbetter
16e83f0b35 Tests: Remove some animation tests from the ignore list
These tests are relevant to the fixes being made in later commits
2025-04-23 09:13:45 +01:00
InvalidUsernameException
84ff18b6ac LibGfx: Assert on out-of-bounds y-value
The reduced amount of indirections from the previous commit made it
obvious that a range check on the y-value was missing.
2025-04-23 09:26:45 +02:00
InvalidUsernameException
7568ea3160 LibGfx: Simplify get_pixel()
There appears to be no reason for Bitmap::get_pixel() to be split into
three layers of methods. Make the code simpler by inlining everything
into a single method.
2025-04-23 09:26:45 +02:00
InvalidUsernameException
578a3af87d LibGfx: Support missing pixel formats in get_pixel()
Bitmap::get_pixel() was only handling two out of the four possible pixel
formats, asserting when called with the other two. The asserting code
path was triggered when loading JPEG XL images, causing crashes on pages
like https://jpegxl.info/resources/jpeg-xl-test-page or
https://html5test.co/.
2025-04-23 09:26:45 +02:00
Shannon Booth
f1d79483b7 LibWeb/HTML: Only trim single '#' on Location.hash setter 2025-04-23 08:24:29 +01:00
Shannon Booth
d01ee20b67 LibWeb/HTML: Update spec comments for location hash setter
Corresponds to open merge request in HTML spec of whatwg/html#11245
and a WPT test change of web-platform-tests/wpt#52085.
2025-04-23 08:24:29 +01:00
Shannon Booth
03c487eb56 LibWeb/HTML: Implement remaining Location setters 2025-04-23 08:24:29 +01:00
Shannon Booth
8ba6c7330d LibWeb/HTML: Adjust some comments in Location implementation
To closer resemble the style of other places in the code base.
2025-04-23 08:24:29 +01:00
Glenn Skrzypczak
d4076ec9fa LibWeb/HTML: Signal a type change
Type changes are now signaled to radio buttons. This causes other radio
buttons in the group to be unchecked if the input element is a checked
radio button after the type change.
2025-04-23 07:20:02 +01:00
Glenn Skrzypczak
5f75558646 LibWeb/HTML: Correctly reset selection on type change
The selection now gets reset to the beginning of the control if the
type changes from an unselectable type to a selectable type.
2025-04-23 07:20:02 +01:00
Pavel Shliak
84e29f791c Revert "AK: Work around Apple Clang __builtin_subc codegen issue"
This reverts commit 9d4dfc1061.
2025-04-22 22:31:28 -06:00
Jonne Ransijn
bb20a0d8f8 AK: Allow the Optional<T> move assignment operator to be trivial
This will change behaviour for moved-from `Optional<T>`s, since they
will now no longer clear their value if `T` is trivial. However, a
moved-from value should be considered to be in an unspecified state.
Use `Optional<T>::clear` or `Optional<T>::release_value` instead.
2025-04-22 21:19:31 -06:00
Jonne Ransijn
50bc6fb9d9 AK: Loosen the restrictions on non-copyable/non-movable containers
If a type is non-move constructible but move assignable,
its container type may still be move assignable.

Similairly, if a type is non-copy constructible but copy assignable,
its container type may still be copy assignable.
2025-04-22 21:19:31 -06:00
Jonne Ransijn
eff9d4881c AK: Add IsScalar to StdLibExtraDetails.h
This matches the behaviour of `std::is_scalar_v`
2025-04-22 21:19:31 -06:00
Jonne Ransijn
0d1ba5c37d AK: Add IsMemberPointer to StdLibExtraDetails.h
Does exactly what it says on the tin.
2025-04-22 21:19:31 -06:00
Jonne Ransijn
7fcedae610 Tests: Fix missing argument removed by -cc1
This argument is removed (or rather, never added) by `-cc1`, which
breaks any builds using GNU libc++, including CI.
2025-04-22 21:19:31 -06:00
Jonne Ransijn
ca33899370 LibJS: Allow Optional<Completion> to be used in constant expressions 2025-04-22 21:19:31 -06:00
Jonne Ransijn
c63a8c0334 LibJS: Allow Optional<Value> to be used in constant expressions 2025-04-22 21:19:31 -06:00
Jonne Ransijn
e37377600d AK: Allow Optional<{,Fly}String> to be used in constant expressions 2025-04-22 21:19:31 -06:00
Jonne Ransijn
a059ab4677 AK: Allow Optional<T> to be used in constant expressions 2025-04-22 21:19:31 -06:00
Jonne Ransijn
063be28e90 AK: Add IsOneOfIgnoringCVReference to StdLibExtraDetails.h
Much like `IsOneOfIgnoringCV`, some functions want to ignore both
cv-qualifiers _and_ references. Add a template and concept for it.
2025-04-22 21:19:31 -06:00
Jonne Ransijn
e5d89c72a6 LibWeb: Remove unuses variable in PaintableBox.cpp 2025-04-22 21:19:31 -06:00
Timothy Flynn
16c535a6d2 Meta: Read vcpkg baseline revision from vcpkg.json
Just so we only have to update one location when we update the baseline.
2025-04-22 19:30:07 -04:00
Ali Mohammad Pur
2c13504bfc LibWebView+RequestServer: Add some UI for DNS settings 2025-04-22 18:05:07 -04:00
Andrew Kaster
e1369aa7d6 CMake: Explicitly set CMAKE_OSX_SYSROOT to macosx for macOS host builds
The implicit default CMAKE_OSX_SYSROOT was a workaround in CMake for
macOS ~10.8. As of CMake 4.x, CMake expects macOS host compilers to have
their own default sysroot detection logic. However, upstream llvm does
not actually do this, only Apple Clang does. To keep supporting homebrew
clang and manually compiled clang from llvm/llvm-project, we need to
set the sysroot explicitly.

The behavior difference and lack of default detection logic in the clang
driver is tracked at https://gitlab.kitware.com/cmake/cmake/-/issues/26863
2025-04-22 17:31:12 -04:00
Aliaksandr Kalenik
981e465a04 LibJS: Delete create_variable param in BindingPattern::generate_bytecode
It's no longer used, because we assume that caller of this function has
already taken care of variable creation and initialization.
2025-04-22 21:57:25 +02:00
Aliaksandr Kalenik
7932091e02 LibJS: Allow using local variable for catch parameters
Local variables are faster to access and if all catch parameters are
locals we can skip lexical environment allocation.
2025-04-22 21:57:25 +02:00
Aliaksandr Kalenik
0f14c70252 LibJS: Use Identifier to represent CatchClause parameter names
By doing that we consistently use Identifier node for identifiers and
also enable mechanism that registers identifiers in a corresponding
ScopePusher for catch parameters, which is necessary for work in the
upcoming changes.
2025-04-22 21:57:25 +02:00
Andreas Kling
42f72bbdce Revert "LibWeb: Turn Window.scroll(0, 0) into a no-op when possible"
This reverts commit 9840a8c750.

Regressed a number of CSS transitions tests in WPT.
2025-04-22 19:28:06 +02:00
Sam Atkins
7bedc1c556 Meta: Update woff2 to version 1.0.2#5
This includes a patch which lets it build on GCC 15.
See https://github.com/microsoft/vcpkg/pull/45132
2025-04-22 11:51:02 -04:00
Sam Atkins
da5a9e548d Meta: Update vcpkg to latest master 2025-04-22 11:51:02 -04:00
Shannon Booth
e124ef52ee LibJS+LibWeb: Set [[CanBlock]] false to Agent for window agent
similar-origin window agents have the [[CanBlock]] flag set to false.
Achieve this by hooking up JS's concept with an agent to HTML::Agent.
For now, this is only hooked up to the similar-origin window agent
case but should be extended to the other agent types in the future.
2025-04-22 11:50:35 -04:00
Timothy Flynn
4cd186f3f5 LibWeb: Adjust the scroll offset when the scrollbar gutter is clicked
This allows clicking on the scrollbar gutter to scroll to the offset
indicated by the mouse position.
2025-04-22 11:29:06 -04:00
Timothy Flynn
a135ce528e LibWeb: Move adjustmust of scrollbar offset into compute_scrollbar_data
Currently, compute_scrollbar_data does not adjust the position of the
scrollbar thumb based on the actual scroll offset. This is because we
perform this offset in most cases inside the display list executor, in
order to allow us to avoid recomputing the display list.

However, there are cases where we do want the thumb rect with an offset
inside PaintableBox. We currently use scroll_thumb_rect to perform that
computation.

In an upcoming patch, we will need both this offset thumb rect and the
scrollbar gutter rect. So this patch moves the computation of the offset
to compute_scrollbar_data, performed behind an optional parameter.
2025-04-22 11:29:06 -04:00
Timothy Flynn
66e422b4f1 LibWeb: Draw a scrollbar gutter when the scrollbar is enlarged 2025-04-22 11:29:06 -04:00
Timothy Flynn
126be42cfa LibWeb: Paint scrollbar outlines with anti-aliasing
This gives the scrollbar a much less jagged appearance.
2025-04-22 11:29:06 -04:00
Timothy Flynn
843468dbf8 LibWeb: Enlarge scrollbars that are interacting with the mouse
When a scrollbar is not interacting with the mouse, we now draw the
scrollbar slightly slimmer. When the mouse enters the space occupied
by the scrollbar, we enlarge it for easier mouse interactivity.
2025-04-22 11:29:06 -04:00
Timothy Flynn
9ef3fd0922 headless-browser: Disable viewport scrollbar painting for tests
This allows us to update how the viewport scrollbar is painted without
breaking every screenshot test.
2025-04-22 11:29:06 -04:00
Shannon Booth
96f38dc180 LibWeb/HTML: Make environments top level creation URL nullable
This is explicitly set to null for Workers.
2025-04-22 08:44:50 -06:00
Ali Mohammad Pur
a786269687 LibWeb/WebAssembly: Implement Module::customSections(module) 2025-04-22 08:43:46 -06:00
Ali Mohammad Pur
f341bb0522 IDLGenerators: Cast wrapped references to a known reference type
They may be GC::Ref<T> objects, which should be converted to T const&
before being so nicely const-cast to T&.
2025-04-22 08:43:46 -06:00
Ali Mohammad Pur
95cc2bd810 LibWeb/WebAssembly: Implement Module::exports(module) 2025-04-22 08:43:46 -06:00
Ali Mohammad Pur
f984c1cc51 LibWeb/WebAssembly: Implement Module::imports(module) 2025-04-22 08:43:46 -06:00
Ali Mohammad Pur
3a6b6a732e IDLGenerators: Unbreak sequence<dictionary> codegen
This was completely busted (where it would generate a variable inside a
block, and try to access it outside the block); this commit fixes this
in the least annoying way possible.
2025-04-22 08:43:46 -06:00
Ali Mohammad Pur
51bab5b186 LibWasm: Make traps hold on to externally-managed data
...instead of specially handling JS::Completion.
This makes it possible for LibWeb/LibJS to have full control over how
these things are made, stored, and visited (whenever).

Fixes an issue where we couldn't roundtrip a JS exception through Wasm.
2025-04-22 08:43:46 -06:00
Andreas Kling
7b2a427430 LibWeb: Avoid computing automatic minimum size for some flex items
There's a specific (and thankfully very common!) scenario where we can
actually skip calculating the automatic minimum size for flex items.

In single-line (no wrapping) flex containers, if the sum of all item
flex base sizes is <= the flex container's main size, we know that
none of the items will be shrunk by the layout algorithm.

And so for any flex item with definite main size AND automatic minimum
main size, we can treat the automatic minimum size as 0.
2025-04-22 15:46:10 +02:00
Tim Ledbetter
6f5b107fcc LibWeb: Resolve absolute calc() values in color functions
Currently, `calc()` values with relative units are not handled
correctly and will output an error to the console.
2025-04-22 12:20:26 +02:00
Tim Ledbetter
9cf04f40f6 LibWeb: Implement the color-mix() function
This takes 2 color values and returns the result of mixing them by a
given amount.
2025-04-22 12:19:51 +02:00
Shannon Booth
a14711a9d7 LibWeb/Bindings: Use realm's globalObject as thisValue if nullish
We were missing the step to use realm's global object if thisValue
was nullish. This is very trivial to fix, as `impl_this` already
handles everything as it should, allowing us to also remove the
special casing for WindowProxy.
2025-04-22 12:17:14 +02:00
Shannon Booth
dcc7fe3663 LibWeb/Tests: Import WPT test global-object-implicit-this-value 2025-04-22 12:17:14 +02:00
Andreas Kling
0c6ad0a740 LibWeb: Remove redundant call to fit-content sizing in flex layout
We were calculating the fit-content cross size and then throwing it
away and doing it again. You might think this wasn't so bad since
fit-content relies on cacheable intrinsic sizes *buuuuut* since we're
actually modifying the constraints for the second call, we were indeed
doing completely wasted work here.
2025-04-22 12:09:42 +02:00
Andreas Kling
9840a8c750 LibWeb: Turn Window.scroll(0, 0) into a no-op when possible
For unscrolled viewports (already at 0, 0), we can short-circuit here
and avoid doing a synchronous relayout of the page.

This avoids a bunch of synchronous layouts on Speedometer3's NewsSite
(Nuxt version) subtests.
2025-04-22 12:09:42 +02:00
Andreas Kling
1242b9152e LibWeb: Turn Element.scroll(0, 0) into a no-op when possible
For unscrolled elements (already at 0, 0) that aren't eligible to be the
Document.scrollingElement, we can short-circuit here and avoid doing a
synchronous relayout of the page.

This avoids a bunch of synchronous layouts on Speedometer3's NewsSite
subtests.
2025-04-22 12:09:42 +02:00
Andreas Kling
c394344e7d LibWeb: Put PaintableWithLines in dedicated GC allocator 2025-04-22 12:09:42 +02:00
Aliaksandr Kalenik
20c6c4e359 LibJS: Delete unused member in FunctionParameter AST node 2025-04-22 10:53:59 +02:00
Shannon Booth
ad62af3d82 LibWeb/ServiceWorker: Add some FIXME comments for updatedResources logic 2025-04-21 15:26:38 -06:00
Shannon Booth
73b981e339 LibWeb/ServiceWorker: Adjust comments for ServiceWorkerRecord 2025-04-21 15:26:38 -06:00
Shannon Booth
9bc022c229 LibWeb/ServiceWorker: Immediately finish job if resources didn't change 2025-04-21 15:26:38 -06:00
Aliaksandr Kalenik
63f17a4f12 LibWeb: Support per-glyph font fallbacks in canvas text measuring 2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
f6b0851c38 LibGfx+LibWeb: Support per-glyph font fallbacks in canvas text painting
Instead of using the first font from the FontCascadeList for all glyphs
in a text, we perform a text shaping process that finds a suitable font
for each glyph and returns a list of glyph runs, where each glyph run
represents consecutive glyphs using the same font.
2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
1e7922fac8 LibGfx+LibWeb: Add Path::glyph_run() and use in canvas
Canvas text painting needs to support per-glyph font fallbacks, which
means we can't hand over responsibility for text shaping to Skia and
instead need to extract glyph paths from our own shaped GlyphRun.
2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
2c64c6d773 LibWeb: Store FontCascadeList instead of Font in CanvasState
This is required to implement per-glyph font fallbacks in the upcoming
changes.
2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
455700d379 LibGfx: Join SkiaFont.cpp into Font
No need to keep this function in a separate file.
2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
8e2d1559ec LibGfx: Join ScaledFont into Font
Since ScaledFont is the only class inherited from Font we could simply
merge them.
2025-04-21 09:51:16 +02:00
Aliaksandr Kalenik
16e883a9a3 LibGfx+LibWeb: Don't include start.x in GlyphRun width
For some reason we were including x offset of start position into glyph
run width. This is not correct and would be revealed by the upcoming
changes.
2025-04-21 09:51:16 +02:00
Timothy Flynn
2b7b7d4d23 Revert "LibWeb: Mark body stream with a TypeError if the request failed"
This reverts commit 4d0301d2d2.

This caused /html/dom/reflection-embedded.html to massively regress.
2025-04-21 09:06:15 +02:00
Andreas Kling
545ed08519 LibWeb: Add debug logging of reasons for layout tree update 2025-04-21 00:31:08 +02:00
Andreas Kling
fa9c463ffd LibWeb: Allow anonymous layout boxes to keep their intrinsic size cache
Instead of indiscriminately clearing the cache for all anonymous boxes,
we now only clear it for those that were generated by a non-anonymous
box in need of layout update.

This increases the cache hit rate and allows us to avoid more work.
2025-04-21 00:31:08 +02:00
Andreas Kling
3ca38505fa LibWeb: Rebuild parent element's layout tree on <object> update
These elements are quite special, so let's treat them like we do for
substantial CSS display changes and rebuild the layout tree starting
from the parent element instead of self.
2025-04-21 00:31:08 +02:00
Andreas Kling
3c15fec303 LibWeb: Move "needs layout update" flag from DOM to layout tree
This is in preparation for allowing anonymous boxes to retain their
intrinsic size cache across layouts.
2025-04-21 00:31:08 +02:00
Andreas Kling
a122685896 LibWeb: Don't look for animations to activate in disconnected subtrees
Knocks down a 3.3% profile item to 1.6% on Speedometer 3.
2025-04-20 18:43:11 +02:00
Andreas Kling
a6dfc74e93 LibWeb: Only set prototype once for object with IDL interface
Before this change, we were going through the chain of base classes for
each IDL interface object and having them set the prototype to their
prototype.

Instead of doing that, reorder things so that we set the right prototype
immediately in Foo::initialize(), and then don't bother in all the base
class overrides.

This knocks off a ~1% profile item on Speedometer 3.
2025-04-20 18:43:11 +02:00
Andreas Kling
7884e58b5c LibWeb: Make Element::html_uppercased_qualified_name() lazy
Many elements never end up needing this string, so instead of eagerly
generating it in the Element constructor, let's defer it until someone
actually requests it.

Knocks off a ~1% profile item on Speedometer3's jQuery test.
2025-04-20 18:43:11 +02:00
Andreas Kling
94cc4adefd LibWeb: Create Element::attributes (NamedNodeMap) lazily
Many elements have zero attributes, and they don't need a NamedNodeMap
until someone asks for it.
2025-04-20 18:43:11 +02:00
Andreas Kling
5085b0dd66 LibWeb: Remove unused HTMLToken::Position::byte_offset 2025-04-20 18:43:11 +02:00
Andreas Kling
669b1131ad LibJS: Streamline CreateMappedArgumentsObject [[ParameterMap]] creation
Instead of using the more generic define_native_accessor() here,
we poke directly at indexed property storage for the parameter map.

We can also construct the NativeFunction objects directly, without
giving them names like "get 0" etc, since these are not observable
by userspace.

Finally, by using default property attributes (not observable anyway),
we get simple indexed storage instead of generic (hash map) storage.
2025-04-20 18:43:11 +02:00
Andreas Kling
5290dcf650 LibJS: Don't create a GC::Function for every JS::NativeFunction
Instead, let JS::NativeFunction store the AK::Function directly, and
take care of conservatively marking its captured data.

This avoids an extra GC allocation for every JS::NativeFunction.
2025-04-20 18:43:11 +02:00
Tim Ledbetter
4283c73d02 LibWeb: Return correct computed value for lab-like and lch-like colors 2025-04-20 16:51:20 +02:00
Tim Ledbetter
e860dd4f65 LibWeb: Implement serialization of lch-like color values 2025-04-20 16:51:20 +02:00
Tim Ledbetter
5074d90888 LibWeb: Implement serialization of lab-like color values 2025-04-20 16:51:20 +02:00
Timothy Flynn
4d0301d2d2 LibWeb: Mark fetched body streams with a TypeError if the request failed
This will cause an exception to be thrown if user attempts to read from
the response stream of a failed request.

This is unfortunately not testable in CI. It requires a network response
(i.e. not a file:// URL). We also cannot import relevant WPT tests; they
exercise this condition with a python-generated response.
2025-04-20 16:50:37 +02:00
Timothy Flynn
b54a520b69 LibRequests+RequestServer: Add an error code for bad content encoding
This error is set by curl when, e.g., a gzipped response body has an
invalid gzip encoding.
2025-04-20 16:50:37 +02:00
Timothy Flynn
e0c4801e0f RequestServer: Ignore CURLE_RECV_ERROR in some cases
The HTTPS server used by WPT will close TLS connections without sending
a "close notify" alert. For responses that did not have a Content-Length
header, curl treats this as an error.
2025-04-20 16:50:37 +02:00
Andreas Kling
0c0650e60a LibWeb: Implement more of the "script-blocking style sheet" mechanism
The basic idea is that style sheets can block script execution under
some circumstances. With this commit, we now handle the simplest cases
where a parser-inserted link element gets to download its style sheet
before script execution continues.

This improves performance on Speedometer 3 where JavaScript APIs that
depend on layout results (like Element.scrollIntoView()) would get
called too early (before the relevant CSS was downloaded), and so we'd
perform premature layout work. This work then had to be redone after
downloading the CSS anyway, wasting time.

Note that our Text/input/link-re-enable-crash.html test had to be
tweaked after these changes, since it relied on the old, incorrect,
behavior where scripts would run before downloading CSS.
2025-04-20 14:54:21 +02:00
Shannon Booth
8e37cd2f71 LibURL: Remove URL's valid state
No code now relies on using URL's valid state.

A URL can still be _technically_ invalid through use of the URL
constructor or by directly changing URL fields.

However, all URLs should be constructed through the URL parser,
and we should ideally be getting rid of the default constructor
at some stage.

Also, any code which is manually setting URL fields need to be
aware that this is full of pitfalls since there are many different
forms of canonicalization which is bypassed by not going through
the URL parser.
2025-04-19 07:18:43 -04:00
Shannon Booth
8d0fb91450 Headless: Remove uneeded URL validity check
All of the URLs in the browser options must be valid.
2025-04-19 07:18:43 -04:00
Shannon Booth
8794bf568a LibWebView: Remove uneeded URL valdity check in CookieJar
The URL given will always be valid.
2025-04-19 07:18:43 -04:00
Shannon Booth
f48b760011 LibWeb/CSS: Avoid URL validity check parsing CSS URLs 2025-04-19 07:18:43 -04:00
Shannon Booth
733dfdaa05 LibWeb: Avoid URL validity check for 'Resource'
Which was previously signally an invalid Resource by a default
constructed invalid URL. Instead, switch this over to an Optional
URL.
2025-04-19 07:18:43 -04:00
Shannon Booth
8ab541b3f6 LibCore: Remove URL validity check for parsing URL's
Now that URL does not implicitly construct from a String, it is
safe to rely on always being passed a valid URL.
2025-04-19 07:18:43 -04:00
Shannon Booth
00bbb2105b LibURL: Port create_with_file_scheme to Optional
Removing one of the main remaining users of URL valid state.
2025-04-19 07:18:43 -04:00
Shannon Booth
2072eee83d LibURL: Implement create_with_file_scheme using URL Parser
Creating a URL should almost always go through the URLParser to
handle all of the small edge cases involved. This reduces the
need for URL valid state.
2025-04-19 07:18:43 -04:00
Glenn Skrzypczak
9c758e5f65 LibWeb/HTML: Correctly parse milliseconds in time inputs
This commit brings the way we parse time inputs closer to the spec by
no longer ignoring milliseconds in time strings.
2025-04-19 07:09:36 -04:00
Glenn Skrzypczak
d37d0e4b59 LibWeb: Prevent crash when encoding into detached buffer
This handles the case where data is encoded into a detached buffer.
2025-04-19 07:08:12 -04:00
Timothy Flynn
8ec420bc28 LibGC: Allow move-assigning RootVector instances
Rule of 5 - we were missing a move-assignment operator, thus all move
assignments resulted in a copy.
2025-04-19 02:03:43 +02:00
Andreas Kling
e0b32b1863 LibJS: Use premade shape when creating mapped arguments objects
Knocks out a 0.4% profile item on Speedometer 3.
2025-04-19 01:14:02 +02:00
Andreas Kling
ed5ad267c7 LibWeb: Keep harfbuzz hb_buffer instead of reallocating every time
Easy 1% speed-up on Speedometer 3.
2025-04-19 01:14:02 +02:00
Andreas Kling
5df3838a80 LibWeb: Evaluate style sheet media rules immediately on insertion
Before this change, we were waiting for Document to lazily evaluate
sheet media and media rules. This often meant that we'd get two
full-document style invalidations: one from adding a new style sheet,
and one from the media queries changing state.

By evaluating the rules eagerly on insertion, we coalesce the two
invalidations into one. This reduces the number of full-document
invalidations on Speedometer 3 from 51 to 34.
2025-04-19 01:14:02 +02:00
Andreas Kling
28d564197c LibWeb: Compute containing block boxes once at start of layout
We now cache the containing block (box) once at the start of layout,
which allows Layout::Node::containing_block() to return instantly
instead of doing tree traversal.

Removes a 0.7% profile item on Speedometer 3.
2025-04-19 01:14:02 +02:00
Ali Mohammad Pur
3b4a184f1a LibRegex: Avoid hashing the state hashes again
We already had a really nice hash that had a single issue, this commit
fixes that and makes it *the* hash for the hash table, so we avoid
double-hashing and making a long chain.
This is an easy 10% perf gain.
2025-04-18 17:09:27 +02:00
Ali Mohammad Pur
446a453719 LibRegex: Pull out the first compare to avoid unnecessary execution
This adds a fast-path to drop view indices we know will not match
immediately without going through the regex VM.
2025-04-18 17:09:27 +02:00
Ali Mohammad Pur
76f5dce3db LibRegex: Flatten capture group list in MatchState
This makes copying the capture group COWVector significantly cheaper,
as we no longer have to run any constructors for it - just memcpy.
2025-04-18 17:09:27 +02:00
Andreas Kling
bbef0e8375 LibWeb: Avoid dynamic_cast in DOM::Document::is_decoded_svg() 2025-04-18 14:45:56 +02:00
Andreas Kling
ce263eaf78 LibWeb: Avoid dynamic_cast in relevant_agent()
There's only ever one kind of JS::VM::CustomData in play anyway.
2025-04-18 14:45:56 +02:00
Andreas Kling
57809b1100 LibWeb: Skip dynamic_cast in CSSRGB after we already did a type check 2025-04-18 14:45:56 +02:00
Andreas Kling
d8188c9f14 LibJS+LibWeb: Add JS::Object::fast_is<T> helpers for some LibWeb types
These are slightly unfortunate as we're crossing the library boundary,
but there's precedent with Object::is_dom_node(), and these are just
knocking down a few more items that were showing up in profiles.
2025-04-18 14:45:56 +02:00
Andreas Kling
207afb0d3b LibWeb: Avoid double dynamic_cast in parent_element_for_event_dispatch() 2025-04-18 14:45:56 +02:00
Andreas Kling
877391d569 LibWeb: Add more fast_is<T> helpers for layout and paintable nodes 2025-04-18 14:45:56 +02:00
Andreas Kling
aecb144df0 LibWeb: Add more fast_is<T> helpers for DOM::Node subclasses 2025-04-18 14:45:56 +02:00
Andreas Kling
0e490e3352 LibWeb: Add fast_is<T> helpers for Navigable & TraversableNavigable 2025-04-18 14:45:56 +02:00
Andreas Kling
f35069d63b LibJS+LibWeb: Add fast_is<T> helpers for Realm::HostDefined class family 2025-04-18 14:45:56 +02:00
Andreas Kling
a9e415b3c4 LibJS+LibWeb: Add fast_is<T> helpers for HTML::Script class family 2025-04-18 14:45:56 +02:00
Andreas Kling
e7b6b84648 LibWeb: Avoid dynamic_cast in EventTarget initialization
Let's use a virtual to tell if something uses the
WindowOrWorkerGlobalScope mixin instead.
2025-04-18 14:45:56 +02:00
Andreas Kling
84626c7db2 LibJS: Add a bunch of fast_is<T> helpers for commonly checked types
Based on what was hitting dynamic_cast<T> on Speedometer.
2025-04-18 14:45:56 +02:00
Glenn Skrzypczak
c0cbd439a2 LibWeb/HTML: Dispatch command events
Command events are now dispatched when buttons are activated. The
special commands for popovers and dialogs are also implemented.
2025-04-18 12:09:57 +01:00
Glenn Skrzypczak
cce7d8c0fb LibWeb/HTML: Implement CommandEvent class
This implements the `CommandEvent` class.
2025-04-18 12:09:57 +01:00
Glenn Skrzypczak
ffe0b05abd LibWeb/HTML: Add the commandForElement attribute to the button element
This commit adds the commandForElement attribute to the
button element. Executing commands is not implemented yet.
2025-04-18 12:09:57 +01:00
Glenn Skrzypczak
b2db07f002 LibWeb/HTML: Add the command attribute to the button element
This commit adds the getter and setter for the command attribute to the
button element. Executing commands is not implemented yet.
2025-04-18 12:09:57 +01:00
Timothy Flynn
629cd3c42a LibWeb: Sort remaining stream AOs (mostly) in spec order
The remaining AOs can stay where they are. This patch just sorts them in
spec order to match the other AO files. Section 8.1 is last, however, as
these are all templates and need the declarations of other AOs above.
2025-04-18 06:55:40 -04:00
Timothy Flynn
3e8c6dbaff LibWeb: Move TransformStream AOs into their own file
The main streams AO file has gotten very large, and is a bit difficult
to navigate. In an effort to improve DX, this migrates TransformStream
AOs to their own file.
2025-04-18 06:55:40 -04:00
Timothy Flynn
26c01f0957 LibWeb: Move WritableStream AOs into their own file
The main streams AO file has gotten very large, and is a bit difficult
to navigate. In an effort to improve DX, this migrates WritableStream
AOs to their own file.
2025-04-18 06:55:40 -04:00
Timothy Flynn
a9ddd427cb LibWeb: Move ReadableStream AOs into their own file
The main streams AO file has gotten very large, and is a bit difficult
to navigate. In an effort to improve DX, this migrates ReadableStream
AOs to their own file. And the helper classes used for the tee and pipe-
to operations are also in their own files.
2025-04-18 06:55:40 -04:00
Timothy Flynn
c35ef36293 LibWeb: Fix typos in ReadableStream AO names 2025-04-18 06:55:40 -04:00
Sam Atkins
141f6cb392 LibWeb/HTML: Use relevant global object's document in History
Corresponds to dba6e7b6c2
and 4c0401186c

The spec algorithms now use "the relevant global object's associated
document", so remove the concept of the History object itself having an
associated document. The spec has also combined the implementations for
forward/back/go so I've matched that too.
2025-04-18 10:49:56 +02:00
Sam Atkins
5b57856eae LibWeb/HTML: Check associated document is fully active, not the window
This is a spec change, but we already implemented the correct version.

Corresponds to aa39b6b6b0
2025-04-18 10:49:56 +02:00
Sam Atkins
343df5d00f LibWeb: Update focus-related spec text
Corresponds to 03ab71775b

I've also split the `Document::has_focus()` method for clarity. Actually
implementing the "has focus steps" turns out to be quite involved so
I've left it for now.
2025-04-18 10:49:56 +02:00
Sam Atkins
609d568776 LibWeb: Remove "locked for focus" concept
Corresponds to 5ba23f9f6d
2025-04-18 10:49:56 +02:00
Shannon Booth
3e17b1c9ae LibWeb: Make Node::parent_element return GC::Ptr
This is useful for people like myself who run with debug mode to
more reliably get stacktraces without spinning up a debugger.
2025-04-18 10:49:02 +02:00
Shannon Booth
a14481ee05 LibWeb/HTML: Handle no parent element for Element::list_owner
Fixes a crash when running Speedometer 3.0 as reduced in the included
test case.
2025-04-18 10:48:47 +02:00
sideshowbarker
b88fddbf47 FAQ: Add question and answer about ad blocker 2025-04-17 20:00:51 +02:00
Andreas Kling
832b0a0ace LibWeb: Invalidate style when HTMLDialogElement modal state changes
This fixes Layout/input/dialog-open-modal.html which began flaking
super hard after the preceding commits that reduced style invalidation
for focus-related pseudo class selectors.
2025-04-17 19:45:55 +02:00
Andreas Kling
8d51c41a42 LibWeb: Remove no-longer-used StyleInvalidationReasons :^) 2025-04-17 19:45:55 +02:00
Andreas Kling
55ab8ff539 LibWeb: Use optimized invalidation for :active pseudo class 2025-04-17 19:45:55 +02:00
Andreas Kling
6da48c60ca LibWeb: Use optimized invalidation for target-related pseudo classes 2025-04-17 19:45:55 +02:00
Andreas Kling
414e0cc930 LibWeb: Use optimized invalidation for focus-related pseudo classes 2025-04-17 19:45:55 +02:00
Andreas Kling
e1777f6e79 LibWeb: Make :hover invalidation logic reusable for all pseudo classes
We achieve this by keeping track of all checked pseudo class selectors
in the SelectorEngine code. We also give StyleComputer per-pseudo-class
rule caches.
2025-04-17 19:45:55 +02:00
Andreas Kling
ed35f9e7c2 LibWeb: Remove unused MatchingRule::must_be_hovered flag
This was a vestige from an earlier version of hover selector work
avoidance optimizations.
2025-04-17 19:45:55 +02:00
Timothy Flynn
60f667fc5a LibWeb: Use (de)serialization with transfer AOs for structured cloning
This is important, for example, to detach transferred array buffers.
2025-04-17 12:13:13 -04:00
Timothy Flynn
5eab109d85 LibWeb: Update structured deserialization to accept its target realm
This is a formal parameter to this AO in the spec.
2025-04-17 12:13:13 -04:00
Timothy Flynn
0c309d4660 LibWeb: Import detached ReadableStream buffer tests 2025-04-17 12:13:13 -04:00
Timothy Flynn
cef714732e Documentation: Remove now-obsolete patch from Servo's DevTools parser
They have fixed the exception mentioned here, but the script still has
trouble displaying all live-captured packets.
2025-04-17 12:12:50 -04:00
Timothy Flynn
83b6803b32 Documentation: Expand DevTools notes on creating a new Firefox profile
Add a command to create a new Firefox profile, and add `--new-instance`
to the command line when using it.
2025-04-17 12:12:50 -04:00
Vishal Biswas
eb165554e1 LibWeb: Use double type in ProgressEvent
loaded and total should be double as per spec
https://xhr.spec.whatwg.org/#progressevent
2025-04-17 08:28:47 -04:00
Vishal Biswas
d56f6805d3 LibWeb: Mimic if-condition from spec
https://xhr.spec.whatwg.org/#dom-xmlhttprequest-abort
2025-04-17 08:28:47 -04:00
Timothy Flynn
5e9a11b13d LibWebView: Respect autocomplete response Content-Encoding headers
For example, Google uses ISO-8859-1 encoding. This patch allows us to
decode such responses, falling back to UTF-8 if a Content-Type was not
specified or could not be parsed. We should also now handle if decoding
fails, rather than crashing inside JsonParser.
2025-04-17 07:51:43 -04:00
Tim Ledbetter
ca200142e9 LibWeb: Don't construct stylesheet when modifying CSSStyleSheet rules
Previously, `CSSStyleSheet.replace()` and `CSSStyleSheet.replaceSync()`
parsed the given CSS text into a temporary stylesheet object, from
which a list of rules was extracted. Doing this had the unintended
side-effect that a fetch request would be started if the given CSS text
referenced any external resources. This fetch request would cause a
crash, since the temporary stylesheet object didn't set the constructed
flag, or constructor document. We now parse the given CSS text as a
list of rules without constructing a temporary stylesheet.
2025-04-16 22:03:12 +01:00
Timothy Flynn
955f6fc9cb LibWeb: Fulfill TransformStream promises with the correct "reason"
We need to use the reason provided to the abort algorithm, not the one
from the resolved cancel promise (which will be undefined).
2025-04-16 13:15:33 -04:00
Timothy Flynn
f6438e83b8 LibWeb: Import TransformStreams reentrant strategies tests 2025-04-16 13:15:33 -04:00
Timothy Flynn
1673f6783c LibWeb: Import TransformStream error tests 2025-04-16 13:15:33 -04:00
Andrew Kaster
ad00306daf AK: Disallow constness laundering in RefPtr and NonnullRefPtr
This is a re-application of 3c7a0ef1ac

Co-Authored-By: Andreas Kling <andreas@ladybird.org>
2025-04-16 10:41:44 -06:00
Andrew Kaster
5e1b3cdeb9 LibGfx: Pass MetalContext in an NNRP in SkiaBackendContext
Previously we were move()-ing an lvalue reference, which causes
issues with upcoming RefPtr const correctness changes.
2025-04-16 10:41:44 -06:00
Andrew Kaster
02afbf3285 WebDriver: Access global sessions mutably when finding sessions
We grab RefPtr to non-const for the sessions within, so we can't call
const get() on the global maps. That would return a const reference.
2025-04-16 10:41:44 -06:00
Andrew Kaster
ea68944149 LibWeb: Store LibGfx objects in RefPtr to const for draw commands 2025-04-16 10:41:44 -06:00
Andrew Kaster
c36c7ed67b LibWeb: Launder const in CSS::Selector::absolutized when returning self
This const method tries to return a RefPtr to non-const self. That's
not kosher, but fixing it needs some architecture work.
2025-04-16 10:41:44 -06:00
Andrew Kaster
16e764ddb6 LibWasm: Store function references' source module in RefPtr to const 2025-04-16 10:41:44 -06:00
Andrew Kaster
c471faee10 LibJS: Launder const in the parser where required with strict RefPtrs
These places should be updated to not require this hackery, but pulling
on this thread involves touching almost every method in the parser.
2025-04-16 10:41:44 -06:00
Andrew Kaster
59b1fb23a9 LibJS: Remove unused InstructionStreamIterator::source_code getter 2025-04-16 10:41:44 -06:00
Andrew Kaster
703abac9c8 AK: Add const_cast escape hatch for converting const T& to RefPtr<T>
There are parts of the codebase where properly const-correctifying the
the code would be a giant spaghetti mess, so add this loud workaround
to defer the refactoring for later.
2025-04-16 10:41:44 -06:00
Andrew Kaster
6ff0373556 UI: Pass parent WebView by non-const ref when creating children
We need to call non-const methods on this guy and access its members in
a non-const way.
2025-04-16 10:41:44 -06:00
Andrew Kaster
5c4b65996e UI/Qt: Store TVG Image Data in a RefPtr to const
We don't need to mutate this data after it's loaded.
2025-04-16 10:41:44 -06:00
Andrew Kaster
4b7f4aef10 LibWeb: Pass RefPtr to const to ClippableAndScrollable setters
We were already storing the ClipFrame and ScrollFrame in RefPtr to const
but we were passing them as RefPtr to non-const to the setters.
2025-04-16 10:41:44 -06:00
Andrew Kaster
280ae45210 LibWeb: Pass ImageData as non-const to CanvasImageData mixin methods
CRC2D needs to manipulate the ImageData object in put_image_data()
2025-04-16 10:41:44 -06:00
Andrew Kaster
91b549f797 LibGfx+LibWebView+UI: Store Gfx::Bitmap in RefPtr to const 2025-04-16 10:41:44 -06:00
Andrew Kaster
be2dd91289 LibGfx+LibWeb: Store Typeface and Font-related types in RefPtr to const 2025-04-16 10:41:44 -06:00
Andrew Kaster
ffd0259bef LibGfx: Store Core::Resources in RefPtr to const 2025-04-16 10:41:44 -06:00
Andrew Kaster
d1f6f5649e LibWeb: Make storage of CSS::CalculationNodes const-correct
Now we consistently use `RefPtr<CalculationNode const>` for all
CalculationNodes.
2025-04-16 10:41:44 -06:00
Andrew Kaster
6d11414957 LibWeb: Make storage of CSS::StyleValues const-correct
Now we consistently use `RefPtr<StyleValue const>` for all StyleValues.
2025-04-16 10:41:44 -06:00
Timothy Flynn
3fdad8fe22 LibWeb: Update spec steps for closing TransformStreams
This was actually an older change to the Streams spec that we missed
when we implemented TransformStreams. This fixes a crash in the imported
WPT tests.

See: https://github.com/whatwg/streams/commit/007d729
2025-04-16 11:39:25 -04:00
Andrew Kaster
8cfac6ed71 LibWeb: Store a SpeculativeHTMLParser on the HTML Parser
The parser was previously added, but unused. Actually attaching one to
the HTML Parser will let us test the limits of Swift interop.
2025-04-16 09:02:27 -06:00
Andrew Kaster
3c45d155a6 CI: Bump swiftly toolchain version to main-snapshot-2025-04-12
The latest snapshot includes some bug fixes that are required in order
to include LibWeb-Swift.h in our C++ files.
2025-04-16 09:02:27 -06:00
Gingeh
bbf4f546af LibWeb: Only create backdrop when originating element is invalidated 2025-04-16 09:01:08 -06:00
Timothy Flynn
6dd2a4c945 LibWeb: Do not create a RootVector to invoke IDL callbacks
These callbacks are evaluated synchronously via JS::Call. We do not need
to construct an expensive RootVector container just to immediately
invoke the callbacks.

Stylistically, this also helps indicate where the actual arguments start
at the call sites, by wrapping the arguments in braces.
2025-04-16 07:32:02 -04:00
Andreas Kling
ca2f0141f6 LibRegex: Remove unused "simple substring search" optimization
This is not relevant for LibJS since it only works when the input is
UTF-8, and LibJS always provides UTF-16.
2025-04-16 10:04:50 +02:00
Andreas Kling
0c93a07fb1 AK: Shrink Utf16View
Use a sentinel value instead of Optional for the cached length in code
points, shrinking Utf16View from 32 to 24 bytes.
2025-04-16 10:04:50 +02:00
Andreas Kling
7628ddfaf7 AK: Remove endianness override from Utf16View
Utf16View is now always in "host" endian mode. This makes it smaller
and less branchy for everyone!
2025-04-16 10:04:50 +02:00
Andreas Kling
0e9480b944 AK+LibTextCodec: Stop using Utf16View endianness override
This is preparation for removing the endianness override, since it was
only used by a single client: LibTextCodec.

While here, add helpers and make use of simdutf for fast conversion.
2025-04-16 10:04:50 +02:00
Andreas Kling
96f1f15ad6 LibRegex: Remove unused Utf8View/Utf32View support in RegexStringView 2025-04-16 10:04:50 +02:00
Timothy Flynn
b1a189acfa LibWeb: Use WebIDL::invoke_promise_callback in Streams where appropriate
This avoids an issue where rejected JS::Promise types were converted to
a resolved WebIDL::Promise type.
2025-04-15 20:33:30 -04:00
Timothy Flynn
525343ba79 LibWeb: Add an alternative to WebIDL::invoke_callback to return promises
When we need the callback to return a promise, we can use this alternate
invoker to construct the WebIDL::Promise for us. Currently, the Streams
API will use WebIDL::invoke_callback to create a JS::Promise, and then
wrap that result in a resolved WebIDL::Promise. This results in rejected
JS::Promise instances not being propagated.
2025-04-15 20:33:30 -04:00
Timothy Flynn
b324b876f2 LibWeb: Import ReadableStreamTee tests 2025-04-15 20:33:30 -04:00
Timothy Flynn
df1e51b80b LibWeb: Use the correct realm when initializing streams
There is an open issue to clarify exactly what realm is to be used when
creating promises. There are surely many more places we will need to
update to use the correct realm (which will be the realm of `this`'s
relevant global object).
2025-04-15 20:33:11 -04:00
Timothy Flynn
1abf5ce843 LibWeb: Import ReadableStream global tests 2025-04-15 20:33:11 -04:00
Sam Atkins
9f333c424c LibWeb/CSS: Ensure a font source format() only contains one string/ident 2025-04-15 21:40:41 +02:00
Sam Atkins
52a4259ef2 LibWeb/CSS: Make @font-face src parsing more forgiving
As noted in the spec, an invalid (or unsupported) font source should not
make the `src` declaration invalid.
2025-04-15 21:40:41 +02:00
Aliaksandr Kalenik
466c793fdb LibIPC: Use AllocatingMemoryStream in TransportSocket send queue
Memory stream is a more suitable container for the socket send queue,
as using it results in fewer allocations than trying to emulate a stream
using a Vector.
2025-04-15 18:48:53 +02:00
Aliaksandr Kalenik
247f7c5fcc AK: Add peek_some() to AllocatingMemoryStream
Same as read_some(), but doesn't move read position.
2025-04-15 18:48:53 +02:00
Jelle Raaijmakers
edaac0f2ee CI: Add missing event key to JS benchmarks workflow 2025-04-15 14:23:27 +02:00
Jelle Raaijmakers
1b4a4b0225 CI: Use workflow run's event commit SHA for JS benchmarks
Chaining workflows does not cause the subsequently spawned workflow runs
to use the same event, but rather it uses the latest head SHA based on
the branch it runs on. This would cause the JS benchmarks jobs to not be
able to find artifacts (if a new JS repl workflow was started before the
previous one could finish) and/or assign the wrong commit SHA to the
benchmark results.

Since `github.event` contains information about the original workflow
run that spawned the JS benchmarks jobs, we can take the commit SHA from
there and use it to download the correct artifact.
2025-04-15 13:53:07 +02:00
Sam Atkins
c00c0846c0 LibWeb: Don't double-dispatch click events on a label's child input
If the user clicked directly on the input inside a label, then it
already received a click event. Dispatching a second one via the label
is redundant, and means that if the input is a checkbox, it gets its
value toggled twice.
2025-04-15 12:34:24 +01:00
Andreas Kling
81d4ed27d8 LibJS: Add cache for the string "[object Object]"
This is very frequently returned by Object.prototype.toString(),
so we benefit from caching it instead of recreating it every time.

Takes Speedometer2.1/EmberJS-Debug-TodoMVC from ~4000ms to ~3700ms
on my M3 MacBook Pro.
2025-04-15 13:08:27 +02:00
Andreas Kling
e8c351505e LibJS: Use premade shape when creating unmapped arguments objects
Takes Speedometer2.1/EmberJS-Debug-TodoMVC from ~4500ms to ~4000ms
on my M3 MacBook Pro.
2025-04-15 13:08:27 +02:00
Jelle Raaijmakers
1f81f75add CI: Remove concurrency configuration for JS artifacts and benchmarks
We had concurrency set on the JS artifacts and JS benchmarks workflows
causing them to not run in parallel for the same combination of
(workflow, OS name). You'd expect that this causes a FIFO queue to exist
of the jobs to run sequentially, but in reality GitHub maintains a
single job to prioritize and cancels all others. We don't want that for
our artifacts and benchmarks: we want them to run on each push.

For example, a new push could have workflows getting cancelled because
someone restarted a previously failed workflow, resulting in the
following message:

  "Canceling since a higher priority waiting request for [..] exists"

By removing the concurrency setting from these workflows, we make use of
all available runners to execute the jobs and potentially run some of
them in parallel. For the benchmarks however, we currently only have one
matching self-hosted runner per job, and as such they are still not run
in parallel.
2025-04-15 12:47:45 +02:00
Jelle Raaijmakers
d616ab0d95 CI: Remove EOL escapes from single quoted string in js-benchmarks
Don't need these, they mess up the JSON payload.
2025-04-15 10:55:05 +02:00
Jelle Raaijmakers
612b0cdddd CI: Add architecture to js-benchmarks webhook callback 2025-04-15 10:55:05 +02:00
Sam Atkins
c224644bed LibWeb/CSS: Fetch ImageStyleValue images closer to spec
We now don't absolutize the URL during parsing, keeping it as a CSS::URL
object which we then pass to the "fetch an external image for a
stylesheet" algorithm. Our version of this algorithm is a bit ad-hoc,
in order to make use of SharedResourceRequest. To try and reduce
duplication, I've pulled all of fetch_a_style_resource() into a static
function, apart from the "actually do the fetch" step.
2025-04-15 09:54:35 +01:00
Sam Atkins
9f00425dad LibWeb/CSS: Let CSSStyleValue know its CSSStyleSheet
The CSS `fetch_foo()` functions resolve the URL relative to the
CSSStyleSheet if one is provided. So, style values that do so need to
know what CSSStyleSheet they are part of so that, for example, `url
(foo.png)` is loaded relative to the style sheet's URL instead of the
document's one.

That all works without this change because we currently absolutize URLs
during parsing, but we're in the process of stopping that.

This commit adds the infrastructure for telling style values what their
CSSStyleSheet is.
2025-04-15 09:54:35 +01:00
Sam Atkins
bf873a2d5b Tests: Add tests for loading images from an imported style sheet
We previously had no coverage for the situation of "relative-linking to
an image in a style sheet which isn't in the same directory as the
document".
2025-04-15 09:54:35 +01:00
Sam Atkins
aebbb008c1 LibWeb/CSS: Expose owning document of CSSStyleSheet
This will be needed for fetching images from CSS.
2025-04-15 09:54:35 +01:00
Sam Atkins
f1af4bcc58 LibWeb: Include SharedResourceRequest.h where it's used
ImageStyleValue.h can rely on the forward-declaration.
2025-04-15 09:54:35 +01:00
Sam Atkins
3ed59f2bd2 LibWeb/CSS: Make fetch_a_style_resource() fall back to sheet's location
See linked spec issue.
2025-04-15 09:54:35 +01:00
Sam Atkins
43950c7342 LibWeb/CSS: Make fetch_a_style_resource() work with no CSSStyleSheet
See the spec issue in the comments for details. There are situations
where we will need to call this but don't have a CSSStyleSheet to pass
in, but we always have a Document, so use that where possible.
2025-04-15 09:54:35 +01:00
Sam Atkins
f4cfdd704b LibWeb/CSS: Make fetch_a_style_resource() take URLs not strings
The spec has this parameter as "a url or `<url>`", so let's match that.
2025-04-15 09:54:35 +01:00
Sam Atkins
3fe978c8a0 LibWeb/CSS: Set request's referrer in fetch_a_style_resource()
THe `location` is now a URL so we can pass it directly.
2025-04-15 09:54:35 +01:00
Sam Atkins
9284530a9f LibWeb/CSS: Return GC::Ref from style sheet parsing methods
These actually always return a value, despite the `CSSStyleSheet*`
return type. So, make that clearer by returning `GC::Ref<CSSStyleSheet>`
instead. This also means we can remove some ad-hoc error-checking code.
2025-04-15 09:40:38 +01:00
Sam Atkins
2a96a81e68 LibWeb: Move style sheet parsing into create_a_css_style_sheet()
The spec is unclear about when exactly we should parse the style sheet.
Previously we'd do so before calling this algorithm, which was
error-prone, as seen by the bug fixed by the previous commit. The spec
for step 1 of "create a CSS style sheet" says:

1. Create a new CSS style sheet object and set its properties as
   specified.

The definitions linked are UA-defined enough that it seems reasonable to
put the parsing here. That simplifies the user code a little and makes
it harder to mess up. It does raise the question of what to do if
parsing fails. I've matched our previous behaviour by just logging and
returning in that case.

While I'm modifying this method, I've also converted the bool params to
enums so they're a little clearer to read.
2025-04-15 09:40:38 +01:00
Sam Atkins
f29a95e2fe LibWeb: Assign linked style sheet location when parsing it
Before this change, we assigned the style sheet's location *after* its
content rules were parsed and added to it. This meant any `@import`s
would try to fetch their style sheet before they knew the URL they
should fetch it relative to.
2025-04-15 09:40:38 +01:00
Sam Atkins
336ccdb5f1 LibWeb/XML: Treat declared namespaces as valid for attributes
Previously if we encountered any attributes with a namespace other than
`xml` or `xmlns`, we treated it as a parse error. Now, allow it as long
as it's been declared in the current context.

We also handle errors more gracefully - instead of exploding if setting
the namespace fails, treat it as an error and carry on.
2025-04-15 09:39:19 +01:00
Sam Atkins
c99aac4bf0 LibWeb/XML: Make namespace getter reject invalid qualified names
Names like ":hi", "wow:", or "a🅱️c" are invalid, so early-out instead
of searching our namespace stack for matching prefixes.

And also rename the function because it's relevant to attributes too.
2025-04-15 09:39:19 +01:00
Andrew Kaster
7d797b2c32 CMake: Remove warning suppression for unknown attributes
We should take care of these with macros or other means instead of
suppressing them.
2025-04-15 02:19:06 -06:00
Andrew Kaster
5e7e6475c6 AK: Annotate [[no_unique_address]] members with NO_UNIQUE_ADDRESS macro 2025-04-15 02:19:06 -06:00
Andrew Kaster
b133c27305 CMake: Disable [[no_unique_address]] when Swift is enabled
There's an upstream bug on this already.
2025-04-15 02:19:06 -06:00
Andrew Kaster
864ddfb55d AK: Add macro to switch between no_unique_address attribute forms
Also add an escape hatch for completely disabling the annotation.
2025-04-15 02:19:06 -06:00
Aliaksandr Kalenik
a4cc0703d1 LibGfx: Make Skia surface construction/destruction thread-safe
With this change we ensure that Skia surfaces are allowed to be created
or destroyed only by one thread at a time. Not enforcing this before
resulted in "Single owner failure." assertion crashes in debug mode on
pages with canvas elements.
2025-04-15 02:33:32 +02:00
Timothy Flynn
cef7821f53 LibWeb: Unindent looping over a BYOB reader's pull-into requests
This was causing us to hang on some BYOB tests.
2025-04-14 19:56:58 -04:00
Timothy Flynn
f22fa827ec LibWeb: Align some BYOB stream AOs with spec text/reality
A couple of minor things I came across while debugging BYOB streams.
Adjust some spec text to match the latest spec, and use GC::Ref instead
of a raw pointer where applicable.
2025-04-14 19:56:58 -04:00
Timothy Flynn
9d33b3632f LibWeb: Update imported WPT utility file
This changed upstream and affects our ability to import BYOB tests. See:
bc9dcbbf1a
2025-04-14 19:56:58 -04:00
Andrew Kaster
2a15b85658 Documentation: Add instructions for how to enable the Swift build 2025-04-14 16:04:08 -06:00
Timothy Flynn
d5d9d999ae LibWeb: Implement ReadableStream's async iterator 2025-04-14 17:43:11 -04:00
Timothy Flynn
e6463e4ecc LibWeb: Import ReadableStream async iterator tests 2025-04-14 17:43:11 -04:00
Timothy Flynn
c0ead1b01a LibIDL+LibWeb: Begin support for async iterator in IDL
This adds support for async iterators of the form:

    async iterable<value_type>;
    async iterable<value_type>(/* arguments... */);

It does not yet support the value pairs of the form:

    async iterable<key_type, value_type>;
    async iterable<key_type, value_type>(/* arguments... */);

Async iterators have an optional `return` data property. There's not a
particularly good way to know what interfaces implement this property.
So this adds a new extended attribute, DefinesAsyncIteratorReturn, which
interfaces can use to declare their support.
2025-04-14 17:43:11 -04:00
Timothy Flynn
398f1ce2a0 LibIDL: Fix typos in IDL error messages 2025-04-14 17:43:11 -04:00
Timothy Flynn
296a81c4b8 LibWeb: Add Streams to the list of IDL interface namespaces
Otherwise, we are not able to generate a fully qualified name for
Streams objects.
2025-04-14 17:43:11 -04:00
Timothy Flynn
16559002bf LibJS: Fully qualify use of js_undefined in TRY_OR_REJECT macro
This allows this macro to be used in LibWeb.
2025-04-14 17:43:11 -04:00
Timothy Flynn
988df9cc8c LibWeb: Perform writes during ReadableStreamPipeTo asynchronously
I don't quite see what spec text requires this, but it is explicitly
checked by WPT. We used to pass this test, but that regressed after
commit 3c6010c663.
2025-04-14 16:56:15 -04:00
Timothy Flynn
6f6b39ecec LibWeb: Import ReadableStreamPipeTo synchronous writing tests 2025-04-14 16:56:15 -04:00
Timothy Flynn
8599917188 LibWeb: Do not throw exceptions from Promise-type attributes
If an attribute's getter were to throw an exception, we must instead
return a rejected promise. We already supported this behavior for
functions.
2025-04-14 15:50:21 -04:00
Timothy Flynn
40fa5887cc LibWeb: Import the streams IDL harness test
This required a bit of manual manipulation. These tests dynamically
fetch generated IDL files, e.g.:

https://github.com/web-platform-tests/wpt/blob/master/interfaces/streams.idl

Our WPT importer is not able to detect the IDL files that need to be
imported, so dom.idl and streams.idl was copied over manually. Further,
idlharness.js would create URLs of the form "file://interfaces/dom.idl".
So idlharness.js was adapted to create a URL relative to the test file.
2025-04-14 15:50:21 -04:00
Timothy Flynn
500fbcb5b8 Meta: Do not lint IDL files imported from WPT 2025-04-14 15:50:21 -04:00
rmg-x
555c8139d8 LibTLS: Call close() when we receive SSL_ERROR_ZERO_RETURN
If we don't do this, then we endlessly spin trying to read data which
ends up in a deadlock.

The description for SSL_ERROR_ZERO_RETURN states:
> The TLS/SSL connection has been closed. If the protocol version is SSL
> 3.0 or TLS 1.0, this result code is returned only if a closure alert
> has occurred in the protocol, i.e., if the connection has been closed
> cleanly. Note that in this case SSL_ERROR_ZERO_RETURN does not
> necessarily indicate that the underlying transport has been closed.
2025-04-14 21:07:42 +02:00
Kenneth Myhra
b285202951 LibWeb: Widen assertion to avoid accidentally writing to a closed stream
This widens the assertion from only checking if the WritableStream's
state is Errored or Erroring to asserting that the WritableStream is not
in a Writable state.
2025-04-14 14:50:54 -04:00
Mehran Kamal
6ba60188b4 LibWeb+LibGfx: Paint dash array and offset for SVG and Canvas 2025-04-14 18:00:38 +01:00
Mehran Kamal
a64902ba25 LibWeb+LibGfx: Paint miter_limit for SVG and Canvas 2025-04-14 18:00:38 +01:00
Andreas Kling
87ec5b32b0 LibRegex: Use ReadonlySpan to peek into OpCode_Compare LUTs
By the time we're executing bytecode, we know the the bytecode will be
flattened. This means we can use ReadonlySpan to look into it instead of
DisjointChunks::spans(), which allocates.
2025-04-14 17:40:13 +02:00
Andreas Kling
c1c3b01a6c LibRegex: Allow Vector<Match> to use trivial memcpy
Now that Match has no more members that need destruction, we can allow
Vector to memcpy them around.
2025-04-14 17:40:13 +02:00
Andreas Kling
5308d77600 LibRegex: Don't use Optional<T> inside regex::Match
This prevented Match from being trivially copyable, which we want it to
be for fast Vector copying.
2025-04-14 17:40:13 +02:00
Andreas Kling
54edf29f1b LibRegex: Make Match::capture_group_name an index into the string table
This removes another Match member that required destruction. The "API"
for accessing the strings is definitely a bit awkward. We'll think of
something nicer eventually.
2025-04-14 17:40:13 +02:00
Andreas Kling
9d47cc54f8 LibRegex: Remove unused regex::Match::string and unused constructor
This shrinks regex::Match by 8 bytes and removes a member that needs
destruction.
2025-04-14 17:40:13 +02:00
Jelle Raaijmakers
8eb16633fe CI: Fix SHA-256 signature in webhook callback for js-benchmarks workflow 2025-04-14 17:09:41 +02:00
Aliaksandr Kalenik
3e1d718b7f LibWeb: Ignore boxes without layout node in intersection observer steps
Check if box has associated layout node is not mentioned in the spec,
but it is required to match behavior of other browsers that do not
invoke intersection observer steps for boxes without layout node.
2025-04-14 17:01:53 +02:00
Aliaksandr Kalenik
ea8a6b43f7 LibWeb: Reserve zero for not supported transfer type
Previously we were using 0 for both unsupported type and MessagePort,
which led to crashing on attempt to decode unsupported transfer type as
MessagePort.

Fixes crashing on
https://docs.mapbox.com/mapbox-gl-js/clip-layer-building-demo.html
2025-04-14 17:01:41 +02:00
Jelle Raaijmakers
e18e7d6019 CI: Simplify workflow name for js-benchmarks.yml
No need to state 'Run the' part.
2025-04-14 14:15:49 +02:00
Jelle Raaijmakers
e6f674fb7f CI: Run benchmarks on macOS as well
This introduces a matrix for the js-benchmarks workflow and runs both
the Linux x86_64 and macOS arm64 JS repl builds against our benchmarks
repository.
2025-04-14 14:15:49 +02:00
Jelle Raaijmakers
4600f9a5b0 CI: Call benchmarks webhook with curl instead of a dedicated action
The workflow-webhook action that was being used didn't work on macOS or
machines without Docker, so let's create the payload ourselves, sign it
and send it over using plain old `curl`.
2025-04-14 14:15:49 +02:00
Jelle Raaijmakers
458c96727c CI: Install pkg-config in setup
We have this package listed in our build instructions but did not
install it for CI, causing some errors on new/clean runners.
2025-04-14 14:15:49 +02:00
Jelle Raaijmakers
4014930278 CI: Select XCode 16.3 for macOS builds
This is the version running on our self-hosted Mac runner.
2025-04-14 14:15:49 +02:00
Timothy Flynn
3c6010c663 LibWeb: Implement ReadableStreamPipeTo reads with less observability
The spec states:

    Public API must not be used: while reading or writing, or performing
    any of the operations below, the JavaScript-modifiable reader,
    writer, and stream APIs (i.e. methods on the appropriate prototypes)
    must not be used. Instead, the streams must be manipulated directly.

This migrates the default request request we were using to a custom read
request which does not involve extra promises.

I'm not sure about an analogous change with the way we write chunks to
the receiving end. There isn't a "WriteRequest" utility to be used here,
and no matter what AO we use, promises will be involved. Our current
implementation at least does not seem to affect any tests.
2025-04-14 07:38:11 -04:00
Timothy Flynn
99550dc4ad LibWeb: Import ReadableStreamPipeTo observability tests 2025-04-14 07:38:11 -04:00
Sam Atkins
6ff2324f26 LibWeb/DOM: Actually stub out pointer-capture API
For real this time.

This makes panning the KendoReact map widget actually work:
https://www.telerik.com/kendo-react-ui/components/map
2025-04-14 12:55:44 +02:00
sideshowbarker
cfc1fd7305 LibWeb: Handle “default step”/“step scale factor” for more input types
This change adds “default step” and “step scale factor” handling for all
remaining HTMLInputElement input types for which the spec defines such
and that we didn’t yet have handling for.
2025-04-14 09:43:16 +01:00
Simon Farre
55483b0096 LibWeb: Set user activation when this is Document
EventTarget::dispatch_event, per comments, does ad-hoc solution for UA,
and I don't know why it checks if `this` is window or `element`, but
web platform tests would fail, because `this` would actually be a
`Document` type.
2025-04-13 10:36:31 -06:00
Simon Farre
87f6a11e47 LibWeb: Add user activation for pointerdown/up
Fixed FIXME's for pointerdown and pointerup events.
2025-04-13 10:36:31 -06:00
stasoid
a821fc03be Headless: Compile on Windows 2025-04-13 10:19:23 -06:00
stasoid
2ac53794c3 LibCore: Implement System::isatty on Windows
Also fixes a bug introduced in 642b7b6a5e: Core::System functions
expect a handle now, so we have to use _get_osfhandle in STD*_FILENO.
2025-04-13 10:19:23 -06:00
0GreenClover0
c286d38765 Meta: Update vcpkg to latest master
Includes a fix for vcpkg git commands not working in git versions
below 2.35.
2025-04-12 19:14:58 -06:00
Andreas Kling
e068ff5a5d LibWeb: Always store ComputedProperties, even if no invalidations
Before this change, we'd skip storing the new ComputedProperties in
Element::recompute_style() if there was no invalidation needed.

This caused us to lose the information about which properties are
inherited and/or important (which is also carried by ComputedProperties,
but doesn't affect invalidation).

Consequently, we'd then fail to recompute inherited styles, since that
mechanism depends on this data.

The fix is simply to always store the new ComputedProperties.
2025-04-13 00:43:49 +02:00
Luke Wilde
9ba76ea25a Meta: Use presets, chosen clang and explicit sysroot to build fuzzers
This near enough matches what CI does to build fuzzers, with the
differences being the explicit -GNinja and setting CMAKE_OSX_SYSROOT,
as CMake 4 no longer does that for us.
2025-04-12 16:13:15 -06:00
Andreas Kling
2aa6d7636c LibWeb: Invalidate sheet owners after mutating cssText of its rules
This fixes one source of flakiness on WPT (of many) where we wouldn't
recompute style after programmatically altering the contents of a style
sheet, but instead had to wait for something else to cause invalidation.
2025-04-12 14:15:57 +01:00
Andreas Kling
6db20a9453 LibJS: Simplify ECMAScriptFunctionObject.[[Realm]] slot handling
Our engine already keeps track of the home realm for all objects.
This is stored in Shape::realm(). We can use that instead of having
a dedicated member in ESFO for the same pointer.

Since there's always a home realm these days, we can also remove some
outdated fallback code from the days when having a realm was not
guaranteed due to LibWeb shenanigans.
2025-04-12 11:07:48 +02:00
Andreas Kling
e4941a36b0 LibJS: Remove unused struct NativeStackFrame 2025-04-12 11:07:48 +02:00
Andreas Kling
d78e3590d5 LibJS: Don't convert to UTF-8 in order to compare two UTF-16 strings
If we have two PrimitiveString objects that are both backed by UTF-16
data, we don't have to convert them to UTF-8 for equality checking.
Just compare the underlying UTF-16 data. :^)
2025-04-12 11:07:48 +02:00
Andreas Kling
e80d1c1a86 LibJS: Add fast_is<T> for JS::Array (array exotic objects)
Nukes a 0.3% profile item on Speedometer 2.1.
2025-04-12 11:07:48 +02:00
Aliaksandr Kalenik
6507d23e29 LibWeb: Save ScrollState snapshot in DisplayList to avoid race condition
With this change we save a copy of of scroll state at the time of
recording a display list, instead of actual ScrollState pointer that
could be modifed by the main thread while display list is beings
rasterized on the rendering thread, which leads to a frame painted with
inconsistent scroll state.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4288
2025-04-12 02:55:18 +02:00
Sam Atkins
d855adf767 LibWeb: Add slider- prefix to slider pseudo-element names
Corresponds to 9549bb8951
2025-04-11 21:27:47 +01:00
Sam Atkins
11b6bd8138 LibWeb/DOM: Stub out Element pointerevents methods 2025-04-11 21:27:13 +01:00
mikiubo
8ec72d6906 LibUnicode: Avoid rejecting end-of-text position as a valid boundary
When the cursor was positioned at the end of text,
attempting to move it left(using the left arrow key)
would fail because align_boundary() was rejecting
the end-of-text position as a valid boundary.
2025-04-11 15:30:17 -04:00
Timothy Flynn
0b23717bc9 LibWeb/WebDriver: Use WebIDL promise AOs to execute async scripts
This removes the use of `spin_event_loop_until` when waiting for async
script results.
2025-04-11 14:35:37 -04:00
Timothy Flynn
8b7bbc81e3 LibWeb/WebDriver: Execute script bodies in a promise-calling manner
This is a bit of a peculiarity with the synchronous script executor. We
must wrap the script result in a promise.
2025-04-11 14:35:37 -04:00
Timothy Flynn
7539d808cd LibWeb/WebDriver: Add a FIXME about allowing await in script bodies
There will soon only be a couple of remaining script execution WPT
promise.py failures. This comment is to explain why.
2025-04-11 14:35:37 -04:00
Timothy Flynn
eb0a51faf0 LibWeb: Implement ReadableStreamPipeTo according to spec
Our existing implementation of stream piping was extremely ad-hoc. It
did nothing to handle closed/errored streams, and did not read from or
write to streams in a way required by the spec.

This new implementation uses a custom JS::Cell to drive the read/write
loop.
2025-04-11 12:10:46 -04:00
Timothy Flynn
4010c4643a LibWeb: Support removing callbacks from AbortSignal
This will be needed by Streams. To support this, we now store callbacks
in a hash table, keyed by an ID. Callers may use that ID to remove the
callback at a later point.
2025-04-11 12:10:46 -04:00
Timothy Flynn
f268f24dd5 LibWeb: Explicitly rethrow exceptions from writable stream start
This is an editorial change in the Streams spec. See:
https://github.com/whatwg/streams/commit/95a5adf
2025-04-11 12:10:46 -04:00
Timothy Flynn
e9a7694cdb LibWeb: Prefer react_to_promise over upon_fulfillment + upon_rejection
While debugging a spec-compliant implementation of ReadableStreamPipeTo,
I spent a lot of time inspecting promise internals. This is much less
noisy if we halve the number of temporary promises.
2025-04-11 12:10:46 -04:00
Timothy Flynn
3033929bb6 LibWeb: Pass abort signal as its concrete type to ReadableStreamPipeTo
There's no real need to wrap it in a JS::Value just to unrwap it again.
2025-04-11 12:10:46 -04:00
Timothy Flynn
ab43c3be23 LibWeb: Store WritableStream's strategy high water mark as a double
It is received from user JS as a double and is only used as a double in
all subsequent calculations. This bug would cause UBSAN errors in an
upcoming imported WPT test, which passes Infinity as the HWM.

Note there is an equivalent HWM for ReadableStream, which already stores
the value as a double.
2025-04-11 12:10:46 -04:00
Timothy Flynn
1d6e1637cc LibWeb: Implement an AO to close writable streams with error propagation 2025-04-11 12:10:46 -04:00
Timothy Flynn
f7c095a318 LibWeb: Implement an AO to get a promise to wait for promises to settle 2025-04-11 12:10:46 -04:00
Timothy Flynn
cceb4321fc LibGC: Allow visiting vectors with inline capacity
This allows visiting e.g. Vector<Value, 1>.
2025-04-11 12:10:46 -04:00
Aliaksandr Kalenik
87bffe7d22 Tests: Rearrange log order in Messaging-post-channel-over-channel.html
When a message is posted to multiple ports at once, the order in which
the callbacks for these messages are invoked is non-deterministic.
To account for this, the test has been rewritten to accumulate logs
for each port separately, and then print them grouped by port.
2025-04-11 17:13:06 +02:00
Tim Ledbetter
f07a3fe6da LibWeb: Use discrete interpolation for degenerate ratios
Degenerate ratios cannot be interpolated.
2025-04-11 11:38:05 +01:00
Tim Ledbetter
b3980d40f7 LibWeb: Round to the nearest integer when interpolating integer values 2025-04-11 11:31:54 +01:00
Jelle Raaijmakers
8257788a20 LibWeb: Ignore negative margins for margin box rect
Negative margins are processed through the `offset` in layout state, and
should not contribute to the margin box' rect's size or position.

Fixes #4249.
2025-04-11 02:34:28 +01:00
Jelle Raaijmakers
76105d6a02 LibWeb: Use LayoutState::set_content_x/y() where possible
No functional changes.
2025-04-11 02:34:28 +01:00
Jelle Raaijmakers
4a6998497f LibWeb: Don't recalculate margin box rect for preceding floats
We already stored that rect while building up the side data during
floating box layout. No functional changes.
2025-04-11 02:34:28 +01:00
stelar7
0a298dba27 LibWeb/IDB: Dont go back to inactive if we finished during upgrade 2025-04-10 19:12:30 -06:00
stelar7
aa4e303b9f LibWeb/IDB: Make some debug messages more descriptive 2025-04-10 19:12:30 -06:00
stelar7
fc06d088c3 LibWeb/IDB: Implement IDBTransaction::objectStore 2025-04-10 19:12:30 -06:00
stelar7
8fcb54dada LibWeb/IDB: Abort requests in the transactions request list 2025-04-10 19:12:30 -06:00
stelar7
a61315a68e LibWeb/IDB: Use correct wait condition when upgrading database 2025-04-10 19:12:30 -06:00
stelar7
de640ffef4 LibWeb/IDB: Implement auto-commit for IDBTransaction 2025-04-10 19:12:30 -06:00
stelar7
da56c1b1eb LibWeb/IDB: Implement IDBTransaction::commit 2025-04-10 19:12:30 -06:00
stelar7
b6b00acbd1 LibWeb/IDB: Implement abort and wait steps for closing a connection 2025-04-10 19:12:30 -06:00
stelar7
fc93ec135e LibWeb/IDB: Keep track of the connection used to start a transaction 2025-04-10 19:12:30 -06:00
stelar7
d1dabb9039 LibWeb/IDB: Make close_a_database_connection take a GC::Ref 2025-04-10 19:12:30 -06:00
stelar7
7c3de67b16 LibWeb/IDB: Dont set the forced flag when aborting connection 2025-04-10 19:12:30 -06:00
stasoid
32ddeb82d6 LibURL+LibWeb: Remove leading slash when converting url to path
...on Windows
2025-04-10 19:04:21 -06:00
stasoid
5ff32fb090 WebContent: Replace static_assert IPC fixmes with comments
Fixes compilation errors on Windows
2025-04-10 19:03:00 -06:00
stasoid
beb11f0447 RequestServer: Compile on Windows 2025-04-10 19:03:00 -06:00
stasoid
17fcbce324 LibCore: Make single-shot timer objects manually reset on Windows
This fixes a really nasty EventLoop bug which I debugged for 2 weeks.

The spin_until([&]{return completed_tasks == total_tasks;}) in
TraversableNavigable::check_if_unloading_is_canceled spins forever.

Cause of the bug:

check_if_unloading_is_canceled is called deferred

check_if_unloading_is_canceled creates a task:

        queue_global_task(..., [&] {
            ...
            completed_tasks++;
        }));

This task is never executed.

queue_global_task calls TaskQueue::add

void TaskQueue::add(task)
{
    m_tasks.append(task);
    m_event_loop->schedule();
}

void HTML::EventLoop::schedule()
{
    if (!m_system_event_loop_timer)
        m_system_event_loop_timer = Timer::create_single_shot(
            0, // delay
            [&] { process(); });

    if (!m_system_event_loop_timer->is_active())
        m_system_event_loop_timer->restart();
}

EventLoop::process executes one task from task queue and calls
schedule again if there are more tasks.

So task processing relies on one single-shot zero-delay timer,
m_system_event_loop_timer.

Timers and other notification events are handled by Core::EventLoop
and Core::ThreadEventQueue, these are different from HTML::EventLoop
and HTML::TaskQueue mentioned above.

check_if_unloading_is_canceled is called using deferred_invoke
mechanism, different from m_system_event_loop_timer,
see Navigable::navigate and Core::EventLoop::deferred_invoke.

The core of the problem is that Core::EventLoop::pump is called again
(from spin_until) after timer fired but before its handler is executed.

In ThreadEventQueue::process events are moved into local variable before
executing. The first of those events is check_if_unloading_is_canceled.
One of the rest events is Web::HTML::EventLoop::process sheduled in
EventLoop::schedule using m_system_event_loop_timer.
When check_if_unloading_is_canceled calls queue_global_task its
m_system_event_loop_timer is still active because Timer::timer_event
was not yet called, so the timer is not restarted.
But Timer::timer_event (and hence EventLoop::process) will never execute
because check_if_unloading_is_canceled calls spin_until after
queue_global_task, and EventLoop::process is no longer in
event_queue.m_private->queued_events.

By making a single-shot timer manually-reset we are allowing it to fire
several times. So when spin_until is executed m_system_event_loop_timer
is fired again. Not an ideal solution, but this is the best I could
come up with. This commit makes the behavior match EventLoopImplUnix,
in which single-shot timer can also fire several times.

Adding event_queue.process(); at the start of pump like in EvtLoopImplQt
doesn't fix the problem.

Note: Timer::start calls EventReceiver::start_timer, which calls
EventLoop::register_timer with should_reload always set to true
(single-shot vs periodic are handled in Timer::timer_event instead),
so I use static_cast<Timer&>(object).is_single_shot() instead of
!should_reload.
2025-04-10 19:02:03 -06:00
stasoid
2bfed2e417 LibCore: Check for all events in EventLoopImplementationWindows::pump
This fixes the problem when none of the timers or notifiers get
executed if wake() is called frequently.

Note that calling WaitForMultipleObjects repeatedly until it fails
will not work because rapidly firing timer can get all the attention.
That's why I check every event individually with WaitForSingleObject.

This behavior matches EventLoopImplementationUnix.
2025-04-10 19:02:03 -06:00
stasoid
5ea4d26458 LibCore: Don't wait in WaitForMultipleObjects if thread event queue
has pending events in EventLoopImplementationWindows

This matches the behavior of the Linux version:
https://github.com/LadybirdBrowser/ladybird/blob/911cd4aefd0c/Libraries/LibCore/EventLoopImplementationUnix.cpp#L371
2025-04-10 19:02:03 -06:00
stasoid
33457f389d LibCore: Check for null ThreadData in unregister_notifier
and unregister_timer in EventLoopManagerWindows

Destructors for thread local objects are called before destructors of
global not thread local objects.

This is a partial stack of the problem, thread_data is already
destroyed at this point:

>WebContent.exe!Core::ThreadData::the
 WebContent.exe!Core::EventLoopManagerWindows::unregister_notifier
 WebContent.exe!Core::EventLoop::unregister_notifier
 WebContent.exe!Core::Notifier::set_enabled
 WebContent.exe!Core::LocalSocket::~LocalSocket
 WebContent.exe!Requests::RequestClient::~RequestClient
 WebContent.exe!Web::`dynamic atexit destructor for 's_resource_loader'
2025-04-10 19:02:03 -06:00
Aliaksandr Kalenik
b53694b4c0 LibIPC+LibWeb: Delete LargeMessageWrapper workaround in IPC connection
Bring back 2d625f5c23
2025-04-10 23:40:02 +02:00
Aliaksandr Kalenik
681333d329 LibIPC: Protect underlying socket of TransportSocket with RWLock
This is necessary to prevent the socket from being closed while it is
being used for reading or writing.
2025-04-10 23:40:02 +02:00
Aliaksandr Kalenik
14dc7686c3 LibIPC: Change TransportSocket to write large messages in small chunks
Bring back d6080d1fdc with a missing check
whether underlying socket is closed, before accessing `fd()` that is
optional and empty in case of closed socket.
2025-04-10 23:40:02 +02:00
Tim Ledbetter
1ee56d34e7 Revert "LibIPC+LibWeb: Delete LargeMessageWrapper workaround in IPC…
…connection"

This reverts commit 2d625f5c23.
2025-04-10 16:24:38 +01:00
Tim Ledbetter
3fcdbef327 Revert "LibIPC: Change TransportSocket to write large messages in…"
…small chunks.

This reverts commit d6080d1fdc.
2025-04-10 16:24:38 +01:00
Jess
23cdd78f1a LibTest: Ensure other time statistic doesn't underflow 2025-04-10 11:17:06 +02:00
Sam Atkins
9dbeecb73d LibWeb: Correct some spec typos
Corresponds to 285a58bf30
2025-04-10 04:01:37 +02:00
Andreas Kling
4a5863bcdb LibJS: Remove unnecessary FunctionObject::name() virtual
This allows us to remove the BoundFunction::m_name field, which we
were initializing with a formatted FlyString on every function binding,
despite never using it for anything.
2025-04-10 04:01:00 +02:00
Andreas Kling
6bd2cf3195 LibWeb: Make Document::m_shadow_roots an IntrusiveList
This makes unregistering a ShadowRoot O(1) instead of O(n) and erases
a 2.2% item entirely from the Speedometer 2.1 profile.
2025-04-10 04:01:00 +02:00
Aliaksandr Kalenik
2d625f5c23 LibIPC+LibWeb: Delete LargeMessageWrapper workaround in IPC connection
It's no longer needed because TransportSocket is now capable of properly
sending large messages.
2025-04-10 01:30:08 +02:00
Aliaksandr Kalenik
d6080d1fdc LibIPC: Change TransportSocket to write large messages in small chunks
With this change TransportSocket becomes capable of sending large
messages without relying on workarounds, such as sending the message as
a shared memory file descriptor when it can't fully fit into the socket
buffer.

It's implemented by combining all enqueued messages into two buffers:
one for bytes and another for fds, and repeatedly attempts to write them
in smaller chunks, waiting for the socket to become writable again if
the receiver needs time to consume the data.

Another significant improvement brought by this change is that we no
longer drop messages queued for sending if the socket doesn't become
writable after a 100ms timeout. Instead, we return the message to the
send buffer and continue waiting for the socket to become writable.
2025-04-10 01:30:08 +02:00
Andreas Kling
fc111537bb LibJS: Move Value::to_i32() and to_u32() back out-of-line
While good on arm64, this appears to have angered the x86_64 benchmark
runner, so let's just put them back out-of-line.
2025-04-10 00:33:54 +02:00
Andreas Kling
8c8023465b LibJS: Make use of arm64 FJCVTZS instruction if available
FJCVTZS (Floating-point Javascript Convert to Signed fixed-point,
rounding toward Zero) does exactly what we need for ToInt32 in the
JavaScript specification.

This isn't world-changing, but it does give a ~2% boost on compute-
heavy benchmarks like JetStream, so we should obviously use it.
2025-04-09 22:06:49 +02:00
Andreas Kling
938b1e91fe LibJS: Inline the fast path of Value::to_i32() and simplify to_u32()
The fast path of to_i32() can be neatly inlined everywhere, and we still
have to_i32_slow_case() for non-trivial conversions.

For to_u32(), it really can just be implemented as a static cast to i32!
2025-04-09 22:06:49 +02:00
stelar7
f1fba24538 LibWeb/IDB: Add ObjectStore to IDBDatabases store set 2025-04-09 11:48:49 -06:00
stelar7
1fc2d6f1af LibWeb/IDB: Comment out infinite loop while waiting for next PR
Since the steps needed to avoid this loop is quite long,
adding this as a fixme for the future will make this PR easier to review
2025-04-09 11:48:49 -06:00
stelar7
6ec914c7f7 LibWeb/IDB: Add some debug output 2025-04-09 11:48:49 -06:00
stelar7
4084a127de LibWeb/IDB: Change reference to a GC::Ref in abort_a_transaction 2025-04-09 11:48:49 -06:00
stelar7
5298ecfc94 LibWeb/IDB: Implement IDBTransaction attributes
This also uncovered a bug, where the transactions type was never set :^)
2025-04-09 11:48:49 -06:00
stelar7
718c805e95 LibWeb/IDB: Implement IDBObjectStore::deleteIndex 2025-04-09 11:48:49 -06:00
stelar7
fce936e05a LibWeb/IDB: Implement IDBObjectStore::index 2025-04-09 11:48:49 -06:00
stelar7
fba7ad6969 LibWeb/IDB: Implement IDBObjectStore::indexNames 2025-04-09 11:48:49 -06:00
stelar7
3367352991 LibWeb/IDB: Implement IDBObjectStore::createIndex 2025-04-09 11:48:49 -06:00
stelar7
a235dd4300 LibWeb/IDB: Fillout IDBIndex attributes 2025-04-09 11:48:49 -06:00
stelar7
9321ad04c0 LibWeb/IDB: Add internal Index object 2025-04-09 11:48:49 -06:00
Sam Atkins
8beade51e0 LibWeb/CSS: Make it clear that StyleSheet::media() is never null 2025-04-09 18:45:57 +01:00
Sam Atkins
848a250b29 LibWeb/CSS: Mark CSSImportRule.media as nullable
See the linked spec issue for more details. The MediaList can be null
internally, and this was upsetting GCC as it meant our bindings code
was dereferencing a null pointer.
2025-04-09 18:45:57 +01:00
Sam Atkins
0f42d5ec3e LibWeb/CSS: Don't resolve @import URLs until they are used
The regression in the "conditional-CSSGroupingRule" test is we now fail
the "inserting an `@import`" subtests differently and the subtests
aren't independent. Specifically, we don't yet implement the checks in
`CSSRuleList::insert_a_css_rule()` that reject certain rules from being
inserted. Previously we didn't insert the `@import` rule because we
failed to parse its relative URL. Now we parse it correctly, we end up
inserting it.
2025-04-09 18:45:57 +01:00
Sam Atkins
ca0890ce16 LibWeb/CSS: Only try to fetch @imports with a parent style sheet
When `CSSRuleList::remove_a_css_rule()` is called, the removed rule has
its parent style sheet set to null. We shouldn't try to fetch an import
in this case.
2025-04-09 18:45:57 +01:00
Sam Atkins
1d9902e22c Tests: Import some @import tests 2025-04-09 18:45:57 +01:00
Sam Atkins
c679643391 LibWeb/CSS: Extract CSSStyleSheet's ParsingParams code into a method
This repeated code is a bit unwieldy.
2025-04-09 18:45:57 +01:00
Sam Atkins
1abc628cd8 LibWeb/CSS: Allow CSSImportRule's document to be null on construction
It's possible to parse an `@import` rule that isn't attached to a
document. We only actually need it to have one when fetching the linked
style sheet, and that should only happen when the CSSImportRule is
attached to a document. So, we can just accept a null pointer when
constructing it.

We relied on that Document to get the Realm, so pass that in as a
separate parameter.
2025-04-09 18:45:57 +01:00
Sam Atkins
a8ab4d64c4 LibWeb/DOM: Use document's URL as location for inline stylesheets
This is ad-hoc, and the spec doesn't seem to tell us what to actually do
here. Without this, following the spec steps for loading relative
`@import` URLs from a `<style>` tag always fails, because that uses the
parent style sheet's location as the base URL.
2025-04-09 18:45:57 +01:00
Sam Atkins
bc02e3e9a9 LibWeb/CSS: Pass location to parse_a_stylesheet() 2025-04-09 18:45:57 +01:00
Sam Atkins
7216c6b050 LibWeb/CSS: Parse <url> as a new CSS::URL type
Our previous approach to `<url>` had a couple of issues:
- We'd complete the URL during parsing, when we should actually keep it
  as the original string until it's used.
- There's nowhere for us to store `<url-modifier>`s on a `URL::URL`.

So, `CSS::URL` is a solution to this. It holds the original URL string,
and later will also hold any modifiers. This commit parses all `<url>`s
as `CSS::URL`, but then converts it into a `URL::URL`, so no user code
is changed. These will be modified in subsequent commits.

For `@namespace`, we were never supposed to complete the URL at all, so
this makes that more correct already. However, in practice all
`@namespace`s are absolute URLs already, so this should have no
observable effects.
2025-04-09 18:45:57 +01:00
Sam Atkins
c82f4b46a2 LibWeb/CSS: Qualify uses of LibURL
To prepare for introducing a CSS::URL type, we need to qualify any use
of LibURL as `::URL::foo` instead of `URL::foo` so the compiler doesn't
get confused.

Many of these uses will be replaced, but I don't want to mix this in
with what will likely already be a large change.
2025-04-09 18:45:57 +01:00
Sam Atkins
da1ff1ba40 LibWeb/CSS: Store CSSStyleSheet location as a URL
We already have a URL when we construct these, and we want a URL later,
so avoid serializing and re-parsing it.
2025-04-09 18:45:57 +01:00
Viktor Szépe
5cc371d54c LibWeb: Fix typos - act II 2025-04-09 15:05:20 +01:00
Sam Atkins
86be8abfbf LibWeb/CSS: Const-correct ComputedProperties::set_computed_font_list()
This shouldn't be const, and that means the two members don't have to be
mutable.
2025-04-09 15:32:04 +02:00
Aliaksandr Kalenik
db8c443392 Everywhere: Make TransportSocket non-movable
Instead of wrapping all non-movable members of TransportSocket in OwnPtr
to keep it movable, make TransportSocket itself non-movable and wrap it
in OwnPtr.
2025-04-09 15:27:52 +02:00
mkljczk
79c22e0d86 LibWeb: Use font with space in range for first_available_computed_font 2025-04-09 12:14:04 +01:00
Tim Ledbetter
55769be9c6 LibWeb: Don't resolve color components when serializing color functions
Previously, we were incorrectly replacing color components with `None`
values with 0.
2025-04-09 12:11:33 +01:00
Tim Ledbetter
a97fe3123d LibWeb: Don't convert color functions to RGB when resolving color values 2025-04-09 12:11:33 +01:00
Tim Ledbetter
02d34dd021 LibWeb: Rename CSSColor to ColorFunctionStyleValue
This gives a better idea of what the class represents.
2025-04-09 12:11:33 +01:00
Gingeh
972547635f LibWeb: Dispatch pointer events to ::backdrop originating element 2025-04-09 12:10:42 +01:00
Gingeh
4b9f5c6fb8 LibWeb: Generate ::backdrop pseudo-elements 2025-04-09 12:10:42 +01:00
Tim Ledbetter
2a17d6d449 LibWeb: Set clip-path animation type to by-computed-value 2025-04-09 09:02:59 +01:00
Andreas Kling
4e9bc0a437 LibJS: Use a premade shape for NativeFunction with length and name
~2% of the Speedometer 2.1 profile was just repeatedly performing the
shape transitions to add these two properties. We can avoid all that
work by caching a premade shape.
2025-04-09 07:22:01 +02:00
Andreas Kling
dbf6f7944e LibJS: Remove unused prototype parameter for NativeFunction::create() 2025-04-09 07:22:01 +02:00
Andreas Kling
b2779ad9f7 AK: Shrink Utf16View from 40 bytes to 32 bytes
This ends up making RegexStringView smaller, which means less stuff to
copy when forking in the regex engine.

Thanks to Leon for suggesting the [[no_unique_address]] trick!
2025-04-09 07:22:01 +02:00
Andreas Kling
697e87b7bd AK: Make ""_string and ""_fly_string literals skip UTF-8 validation
We still validate in an ASSERT, but let's not bother with this in
release builds.
2025-04-09 07:22:01 +02:00
Timothy Flynn
f070264800 Everywhere: Remove sv suffix from format string literals
This prevents the compile-time checks that would catch errors in the
format invocation (which would usually lead to a runtime crash).
2025-04-08 20:00:18 -04:00
Timothy Flynn
917537b449 AK: Enable compile-time check of a format test string
Our implementation seems to parse this string just fine now.
2025-04-08 20:00:18 -04:00
Timothy Flynn
d5222e9bba LibJS: Do not generate a format string in Number.prototype.toFixed
We can use the placeholder syntax to specify the precision dynamically.
Note that `fraction_digits` is a double, which we do not support as a
precision argument. It's safe to cast to an integer here because we
guaranteed above that the value is in the range [0, 100], and is not
fractional.
2025-04-08 20:00:18 -04:00
Timothy Flynn
64d290447c LibCore+LibJS+LibWasm: Always use a real format string
It's generally considered a security issue to use non-format string
literals. We would likely just crash in practice, but let's avoid the
issue altogether.
2025-04-08 20:00:18 -04:00
Luke Wilde
cd72e788e9 LibWeb: Append style sheet to ShadowRoot's list if link el is in one
We were handling removing the style sheet from the shadow root, but not
appending to it. Fixing this also revealed a bug that a removed link
element would always try to remove from the document's list, as the
root is no longer the shadow root it's in. The fix is to use the passed
in old root to remove the style sheet from.

Fixes the cookie banner on https://nos.nl/
2025-04-08 23:20:54 +02:00
Aliaksandr Kalenik
14bac7b287 LibIPC: Move send thread from IPC connection to the transport layer
By doing this we also make MessagePort, that relies on IPC transport,
to send messages from separate thread, which solves the problem when
WebWorker and WebContent could deadlock if both were trying to post
messages at the same time.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4254
2025-04-08 21:09:24 +02:00
Aliaksandr Kalenik
af2dae63d1 Tests: Rearrange message order in Messaging-post-channel-over-channel
The way this test was written didn't guarantee a deterministic message
order, resulting in different output in Chromium and Firefox. This
change slightly rearranges the message order to make it deterministic.

This change is necessary as a prepartion for upcoming change that makes
MessagePort post messages from a separate thread, which would've
revealed the non-deterministic message order.
2025-04-08 21:09:24 +02:00
Aliaksandr Kalenik
ab35325003 LibIPC: Move early fd deallocation workaround to the transport layer
Reimplements c3121c9d at the transport layer, allowing us to solve the
same problem once, in a single place, for both the LibIPC connection and
MessagePort. This avoids exposing a workaround for a macOS specific Unix
domain socket issue to higher abstraction layers.
2025-04-08 21:09:24 +02:00
Aliaksandr Kalenik
3525467e56 LibIPC: Join send thread instead of detaching in ~ConnectionBase()
By doing this we ensure that sending thread won't try to write into a
closed socket.
2025-04-08 21:09:24 +02:00
Andreas Kling
6362ec6f3d LibJS: Stop passing StringView literals as format strings
This was preventing the format string checks from running, which would
have caught a bug I was about to introduce.
2025-04-08 18:52:35 +02:00
Andreas Kling
4593e19bcf LibJS: Make class-specific members of ESFO lazily allocated
We don't need the [[Fields]] and [[PrivateMethods]] slots for most ESFO
instances, so let's reduce their impact on class size!

This shrinks ESFO from 200 bytes to 160 bytes, allowing more allocations
before we have to collect garbage.
2025-04-08 18:52:35 +02:00
Andreas Kling
2a9b6f1d97 LibJS: Move computation out of the ECMAScriptFunctionObject constructor
We were doing way too much computation every time an ESFO was
instantiated. This was particularly sad, since the results of these
computations were identical every time!

This patch adds a new SharedFunctionInstanceData object that gets
shared between all instances of an ESFO instantiated from some kind of
AST FunctionNode.

~5% speedup on Speedometer 2.1 :^)
2025-04-08 18:52:35 +02:00
Andreas Kling
4209b18b88 LibJS: Add ECMAScriptFunctionObject::create_from_function_node() helper
This gives us a shared entry point for every situation where we
instantiate a function based on a FunctionNode from the AST.
2025-04-08 18:52:35 +02:00
Andreas Kling
ef4e7b7945 LibJS: Make JS parser emit accurate this insights for constructors
This way we don't have to handle it when instantiating the constructor.
2025-04-08 18:52:35 +02:00
Andreas Kling
9c0b185ab8 LibJS: Don't track "last result" of ScopeNode if we don't need it
This prevents unnecessary bytecode register allocation.
2025-04-08 18:52:35 +02:00
Andreas Kling
c845c90e98 LibJS: Avoid GC::RootVector allocations in {Super,}CallWithArgumentArray
We can use the Interpreter::allocate_argument_values() mechanism for
this and avoid creating a temporary RootVector for every such call.
2025-04-08 18:52:35 +02:00
Andreas Kling
5cdbb8b140 LibJS: Remove unused this value from CallConstruct instruction
There's no `this` value prior in the caller context, and this was never
actually used by CallConstruct.
2025-04-08 18:52:35 +02:00
Ali Mohammad Pur
6b883c5ccb Meta: Disable -Warray-bounds and -Wstringop-overflow on GCC
These generate what seems to be nonsense warnings on Function and
ByteBuffer; they *should* be investigated at some point, but they don't
provide anything useful at this point.
2025-04-08 14:01:28 +02:00
Ali Mohammad Pur
0a958c8e16 Meta: Add an option to disable LTO for Release builds 2025-04-08 14:01:28 +02:00
Ali Mohammad Pur
fac2ee4452 Meta: Add a link job pool with a configurable size
Parallel linking (esp. with bfd) uses a huge chunk of memory, make it
possible for users to limit the number of link jobs to at least
limit the pain.
2025-04-08 14:01:28 +02:00
Timothy Flynn
ccf03316fa LibJS: Convert FilterLocales and CoerceOptionsToObject to GC::Ref
These never return nullptr.
2025-04-08 06:50:40 -04:00
Timothy Flynn
2729c88154 LibJS: Migrate remaining Intl objects to use ResolveOptions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/75e67db
2025-04-08 06:50:40 -04:00
Timothy Flynn
3f55240a8e LibJS: Migrate Intl.DisplayNames to use ResolveOptions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/5eafacd
2025-04-08 06:50:40 -04:00
Timothy Flynn
636e214326 LibJS: Migrate Intl.Collator to use ResolveOptions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/f822dc1
2025-04-08 06:50:40 -04:00
Timothy Flynn
e40881ebb8 LibJS: Migrate Intl.DateTimeFormat to use ResolveOptions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/9e4c922
2025-04-08 06:50:40 -04:00
Timothy Flynn
d3332d51b5 LibJS: Add an AO to implement Intl constructor locale resolution
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/9e4c922
2025-04-08 06:50:40 -04:00
Timothy Flynn
62793b1bd8 LibJS: Define constructor slots for describing how to read options
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/a2beb66

We implement this change by introducing a virtual interface that all
Intl "service" objects must implement. A future patch will make use of
the virtualized RelevantExtensionKeys and ResolutionOptionDescriptors
accessors, and we will need to be able to use those slots from a generic
instance type.
2025-04-08 06:50:40 -04:00
Timothy Flynn
19ce186f97 LibJS: Define Intl.Locale's LocaleExtensionKeys more declaratively
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/3898acf
2025-04-08 06:50:40 -04:00
Timothy Flynn
75fce14f09 LibJS: Rename Intl.Locale's RelevantExtensionKeys to LocaleExtensionKeys
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/e2a5747
2025-04-08 06:50:40 -04:00
Timothy Flynn
680f028bb8 LibJS: Simplify Intl.Collator sensitivity / ignorePunctuation defaults
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/23e2e92
2025-04-08 06:50:40 -04:00
Timothy Flynn
b81d0d3261 LibJS: Ensure Intl.Collator instances have [[Numeric]] and [[CaseFirst]]
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/243ec38
2025-04-08 06:50:40 -04:00
Timothy Flynn
0f1fa38442 LibJS: Update spec link for FormatNumericToString AO
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/e3f7260

Note the other changes in this commit do not apply to our implementation
as we defer to ICU for the affected steps.
2025-04-08 06:50:40 -04:00
Andreas Kling
be70f8d345 LibGC: Avoid excessive bitfield use in GC::Cell
We didn't actually save any space by making the Cell flags bitfields.
In fact, it just forced us to do bit twiddling when accessing them.
2025-04-08 12:09:42 +02:00
Sam Atkins
a80408fea6 LibWeb/CSS: Store @property initial value as a style value
For now, it's the "raw" UnresolvedStyleValue. Later, we'll need to try
to parse it into a "real" style value using the property's syntax.
2025-04-08 09:59:41 +01:00
Sam Atkins
9292b769ef LibWeb/CSS: Use descriptor parsing for @property 2025-04-08 09:59:41 +01:00
rmg-x
514233008b Meta+LibCore: Stop linking against LibCrypt
This was only be used by "Account.cpp" which was removed in:
d8c36ed458
2025-04-08 09:13:33 +02:00
rmg-x
92f5183ced AK+Meta: Remove unused class RecursionDecision 2025-04-08 09:13:33 +02:00
rmg-x
fcf3abd19c AK: Remove unused class DOSPackedTime 2025-04-08 09:13:33 +02:00
rmg-x
f39d14fa8a RequestServer: Remove check for square brackets in websocket_connect
This is no longer necessary since commit:
6480e1a3fe
2025-04-08 09:13:33 +02:00
Luke Wilde
948349974c LibWeb/WebGL: Implement EXT_blend_minmax extension 2025-04-07 23:21:11 +02:00
Aliaksandr Kalenik
ac643aa392 LibIPC: Break from message parsing if whole message payload is not ready
Fixes the bug when we try to read message payload without checking if we
received enough bytes or file descriptors.
2025-04-07 20:26:01 +02:00
Timothy Flynn
1d9e226206 AK: Remove unused UTF-8 / other factory methods from ByteString 2025-04-07 17:44:38 +02:00
Timothy Flynn
3f439efe21 AK: Rename StringImpl to ByteStringImpl
StringImpl is very specific to ByteString. Let's rename it to match, to
avoid confusion with the StringBase and StringData classes.
2025-04-07 17:44:38 +02:00
Timothy Flynn
0a256b0a9a AK+Everywhere: Change StringView case conversions to return String
There's a bit of a UTF-8 assumption with this change. But nearly every
caller of these methods were immediately creating a String from the
resulting ByteString anyways.
2025-04-07 17:44:38 +02:00
Timothy Flynn
05627b6f45 AK: Remove unused ByteString titlecase/invert case conversions 2025-04-07 17:44:38 +02:00
Timothy Flynn
c8bb3030fd AK: Return NonnullRefPtr from StringImpl::create methods
None of these return a nullptr.
2025-04-07 17:44:38 +02:00
Timothy Flynn
f029ba6a29 AK: Improve performance of ASCII case conversions
Don't use a Vector to form the transformed string. We can construct the
string immediately and store the result in its buffer, and thus avoid a
double allocation.

In a synthetic benchmark, lowercasing a 500 character ASCII string
1 million times reduced from 550ms to 65ms on my machine.
2025-04-07 17:44:38 +02:00
Timothy Flynn
13d7d3a60d AK: Simplify ASCII case conversion implementations a bit
* Use `any_of` instead of manual loops

* Don't check if a code point is upper/lowercase twice. The check we
  are using is already present inside the case converter.

* Move StringImpl's implementation into ByteString. ByteString is its
  only user, so let's avoid some jumping around. The other ASCII case
  methods on StringImpl will soon also be removed.
2025-04-07 17:44:38 +02:00
Aliaksandr Kalenik
a371f849e3 LibIPC: Make TransportSocket responsible for reading entire messages
With this change, the responsibility for prepending messages with their
size and ensuring the entire message is received before returning it to
the caller is moved to TransportSocket. This removes the need to
duplicate this logic in both LibIPC and MessagePort.

Another advantage of reducing message granularity at IPC::Transport
layer is that it will make it easier to support alternative transport
implementations (like Mach ports, which unlike Unix domain sockets are
not stream oriented).
2025-04-07 16:59:49 +02:00
Shannon Booth
0a58497ab9 LibURL/Pattern: Fix PatternParser logic for prefix codepoint comparison
We were not properly handling the case that prefix code point was the
empty string (which we represent as an OptionalNone). While this
still resulted in the correct pattern string being generated, an
incorrect regular expression was being generated causing matching
to fail.
2025-04-07 10:29:09 -04:00
Shannon Booth
4b6f0ee24a LibURL: Do not trim whitespace parsing port in URL parser
This has no functional difference as far as I can tell, but for
clarity explicitly do not attempt to do this, which has the nice
side effect of not checking for whitespace known to not exist.
2025-04-07 10:29:09 -04:00
Shannon Booth
565ccc04a9 LibURL/Pattern: Do not trim whitespace interpreting port
It turns out that the problem here was simply that we were trimming
trailing whitespace when we did not need to, which was meaning that
the port number of '80 ' was being converted to the empty string
per URLPattern elision as the port matches the http scheme.
2025-04-07 10:29:09 -04:00
Luke Wilde
25e343464d LibJS: Cache length identifier for GetLengthWithThis
We cached the length identifier for GetLength, but not
GetLengthWithThis. This caused an `has_value()` verification failure
when accessing super.length. Found by Fuzzilli.
2025-04-07 14:40:48 +02:00
Tim Ledbetter
408f9f3dde LibWeb: Disallow "default" as a <family-name> identifier
This commit disallows "default" as a font-family name, when the name is
not quoted because unquoted names are treated as custom-idents, for
which the name "default" is not allowed.
2025-04-07 12:14:29 +01:00
Tim Ledbetter
263cb3f8ca LibWeb/CSS: Remove unnecessary shorthand serialization special cases
The serialization of these properties is improved by using the new
default behavior.
2025-04-07 11:38:56 +01:00
Tim Ledbetter
63228477a4 LibWeb/CSS: Specify list-style subproperties in canonical order 2025-04-07 11:38:56 +01:00
Tim Ledbetter
3186adeaa1 LibWeb/CSS: Don't serialize longhands which match their initial values
Shorthand subproperties that match their initial values are now
excluded from serialization, by default.

Properties where this behavior is not desired, like `gap`, are
special-cased.
2025-04-07 11:38:56 +01:00
Viktor Szépe
b4b8d85251 LibWeb+LibJS+Tests: Fix typos - act I 2025-04-07 11:22:13 +01:00
Sam Atkins
e8213bb86b LibWeb/CSS: Remove unnecessary note about unicode-range parsing
I wrote this before implementing the parsing, and it ended-up not being
true.
2025-04-07 10:00:21 +01:00
Sam Atkins
5609649098 Documentation: Document Descriptors.json 2025-04-07 10:00:21 +01:00
Sam Atkins
5aeaeb3097 LibWeb/CSS: Remove redundant font-face src parsing code
We now always parse this as a descriptor.
2025-04-07 10:00:21 +01:00
Sam Atkins
5f6972fc31 LibWeb/CSS: Parse FontFace parameters as descriptors
This also rearranges the code to follow the spec better: We create an
empty FontFace first and then fill it in, instead of creating it
fully-formed at the end.
2025-04-07 10:00:21 +01:00
Sam Atkins
0121e7028f LibWeb/CSS: Make "CSSStyleValue -> list of font sources" code accessible
We'll want this in FontFace.
2025-04-07 10:00:21 +01:00
Sam Atkins
3288c71953 LibGfx: Serialize unicode-ranges in uppercase
This matches the behavior of other browsers.
2025-04-07 10:00:21 +01:00
Sam Atkins
1e132d9f87 LibWeb/CSS: Use descriptor parsing in FontFace setters 2025-04-07 10:00:21 +01:00
Sam Atkins
ce56ac9159 LibWeb/CSS: Correct include style in CSSFontFaceDescriptors.cpp 2025-04-07 10:00:21 +01:00
Sam Atkins
775efd01e2 LibWeb/CSS: Use initial values for @font-face descriptors 2025-04-07 10:00:21 +01:00
Sam Atkins
d2c58e9376 LibWeb/CSS: Generate descriptor initial values
We parse these lazily, and then cache them for future use.
2025-04-07 10:00:21 +01:00
Sam Atkins
ee647616b2 LibWeb/CSS: Serialize @font-face closer to spec
Read the descriptor style values instead of producing a ParsedFontFace
first, as this means we know if a descriptor is actually present, or
has been defaulted to an initial value. This lets us correctly skip the
unicode-range if it was not explicitly set.

Firefox and Chromium both serialize using the "font-stretch" name,
(which is an alias for font-width) which follows the outdated cssom
spec, so I've done so too to match them.

The one thing that we still do differently in this test is that those
browsers check explicitly if `font-stretch` was set, and ignore when
`font-width` is.

I've also inlined the `serialize_a_local()` function to the one place
it's used. The style value to_string() method was already wrapping the
string in quotes, so calling serialize_a_string() on it was producing
`local("\this mess\"")`. It's clearer what's happening when the code
isn't split up.
2025-04-07 10:00:21 +01:00
Sam Atkins
a7f7c2a821 LibWeb/CSS: Teach OpenTypeTaggedStyleValue to serialize without "1" 2025-04-07 10:00:21 +01:00
Ali Mohammad Pur
69050da929 LibRegex: Merge inverse string table mappings separately 2025-04-06 20:21:16 +02:00
Ali Mohammad Pur
299b9ca572 LibRegex: Check backreference index before looking it up
If a backref happens after it's cleared, the slot may be cleared
already.
2025-04-06 20:21:16 +02:00
Andreas Kling
e695dc1405 LibJS: Don't make Bytecode::Operand::Type an u8 outside of aarch64
This is a slightly mystified attempt to recover the performance
regression seen on our JS benchmark runner after 3c2a2bb39f
and c7bba505ea.

With this change, c7bba505ea is effectively reverted from the
perspective of x86_64.
2025-04-06 20:12:58 +02:00
Timothy Flynn
ee6b2db009 AK+LibURL+LibWeb: Use simdutf to validate ASCII strings
simdutf provides a vectorized ASCII validator, so let's use that instead
of looping over strings manually.
2025-04-06 11:05:58 -04:00
Shannon Booth
212095e1c2 LibURL/Pattern: Ensure string passed through in process a URLPatternInit
Corresponds to: https://github.com/whatwg/urlpattern/commit/696b402
2025-04-06 08:24:54 -04:00
Shannon Booth
bee3720b6f LibURL/Pattern: Make dummyURL from the URL parser with a special scheme
Corresponds to: https://github.com/whatwg/urlpattern/commit/46c30fda8f

Along with a follow up bug fix that I made of:

https://github.com/whatwg/urlpattern/commit/5e1c93e2

This for example, fixes canonicalization of URL hosts containing
special characters that should have the unicode ToAscii algorithm
performed on them as the URLs were not being treated as special.
2025-04-06 08:24:54 -04:00
Shannon Booth
83a82a027f LibURL/Pattern: Do not return errors in some canonicalization steps
Corresponds to: https://github.com/whatwg/urlpattern/commit/5c979a31
2025-04-06 08:24:54 -04:00
Shannon Booth
a9777a3300 LibURL: Make port state override return failure more for URLPattern
Corresponds to URL spec change:

https://github.com/whatwg/url/commit/cc8b776b

Note that the new test failure being introduced here is an unrelated
WPT test change bundled in the resources test file update that I am
not convinced is correct.
2025-04-06 08:24:54 -04:00
Shannon Booth
4e8f2e48c4 LibURL: Report all hostname state failures for URLPattern
Corresponds to URL spec change:

https://github.com/whatwg/url/commit/c23aec1
2025-04-06 08:24:54 -04:00
Shannon Booth
f64d5451df LibWeb/Bindings: Do put OptionalNone as member in returned dictionaries
Our handling of 'optional' return values was previously not correct
in that we would always call 'create_data_property' for every
single member of the returned dictionary, even if that property did
not have a value (by falling back to JS::js_null).

This was resulting in a massive number of test failures for URL
pattern which was expecting 'undefined' as the member value, instead
of 'null'.
2025-04-06 08:24:54 -04:00
Shannon Booth
b1b73f32a7 LibWeb/Bindings: Invert logic for nullability check in wrap statements
This is less code, and also makes a future bugfix much simpler to
implement :^)
2025-04-06 08:24:54 -04:00
Shannon Booth
dcb7842f59 LibURL/Pattern: Use opaque pathname serialization in canonicalization
The URL spec represents its path as a:

Variant<String, Vector<String>>

A URL is defined has having an opaque path if it has a single String,
the URL path otherwise containing a list of path components.

We (like in an older version of the spec) track this through a boolean
and only use a Vector with a single component for opaque paths.

This means it was incorrect to simple assign the path to a list with
a single empty string without setting that URL as opaque, which
meant that the path serialization was producing incorrect results.

It may make sense changing the API so this situation is a little more
clear. But for now, we simply need to set the opaque path boolean
to true here.
2025-04-06 08:24:54 -04:00
Shannon Booth
e7ad9a9bad LibURL/Pattern: URL parse correct value in opaque path canonicalization 2025-04-06 08:24:54 -04:00
Shannon Booth
e54504ad93 LibURL/Pattern: Implement 'compute protocol matches a special scheme' 2025-04-06 08:24:54 -04:00
Shannon Booth
6b1fa3ecd0 LibURL/Pattern: Implement matching a URLPattern 2025-04-06 08:24:54 -04:00
Shannon Booth
2a44420e52 LibURL/Pattern: Implement generating a component match result 2025-04-06 08:24:54 -04:00
Shannon Booth
e35555f00e LibURL/Pattern: Complete the implementation of the constructor 2025-04-06 08:24:54 -04:00
Shannon Booth
c9e6ad562c LibURL/Pattern: Implement ability to compile a component
This provides the infrastructure for taking a part list from the
pattern parser and generating the actual regexp object which is
used for matching against URLs from the pattern.
2025-04-06 08:24:54 -04:00
Shannon Booth
934f1ec30d LibURL/Pattern: Implement the URLPattern Pattern Parser 2025-04-06 08:24:54 -04:00
Shannon Booth
45d852d14b LibURL: Add helper for getting array of the special schemes
This is useful for iterating over all of the special schemes, as
needed in the URLPattern implementation.
2025-04-06 08:24:54 -04:00
Shannon Booth
e3ef6d3aee LibURL/Pattern: Implement ability to generate a pattern string
Compiling a URLPattern component will generate a 'parts list' which
is used for generating the regular expression that is used for
matching against URLs.

This parts list is also used to generate (through this function) a
pattern string. The pattern string of a URL component is what is
exposed on the USVString getters of the URLPattern class itself.

As an example, the following:

```
let pattern = new URLPattern({ "pathname": "/foo/(.*)*" });
console.log(pattern.pathname);
```

Will log the pattern string of: '/foo/**'.
2025-04-06 08:24:54 -04:00
Shannon Booth
f3679184cb LibURL/Pattern: Add representation of a URL Pattern 'options' struct
These control how a pattern string is generated, which can vary for
different components and is also impacted by the 'ignoreCase' option
that can be provided in the URLPattern constructor.
2025-04-06 08:24:54 -04:00
Shannon Booth
88bea4a717 LibURL/Pattern: Add a URL Pattern 'Part' representation 2025-04-06 08:24:54 -04:00
Shannon Booth
8a33c57c1e LibWeb/LibURL: Use an IgnoreCase enum for URLPatternOptions
This is to save a future name conflict that will appear between
the options IDL dictionary and the options struct that are both
present in the spec.

It is also a nicer interface for now given there is only a single
option at the moment.
2025-04-06 08:24:54 -04:00
Shannon Booth
f80e7d6816 LibURL/Pattern: Implement processing a URL Pattern Init
This gets us to the point just before the point of parsing the
pattern strings for each URL component to produce a regular
expression.
2025-04-06 08:24:54 -04:00
Shannon Booth
3f73cd30a2 LibURL: Rename 'cannot have a base URL' to 'has an opaque path'
This follows a rename made in the URL specification.
2025-04-06 08:24:54 -04:00
Shannon Booth
6b85748f53 LibURL/Pattern: Implement helper for escaping a URL Pattern String 2025-04-06 08:24:54 -04:00
Andreas Kling
c7bba505ea LibJS: Only use bitfields in Bytecode::Operand on aarch64
It seems both aarch64 and x86_64 are extremely sensitive to the use of
bitfields here. Unfortunately, aarch64 gains a huge speedup from them
while x86_64 sees a very noticeable slowdown.

Since we're talking about 5%+ swings in both directions here, let's go
for the best of both worlds and use ifdefs in the Operand memory layout.
2025-04-06 14:14:34 +02:00
Timothy Flynn
2810071a9c LibWebView: Support custom search engines
This allows the user to store custom search engines via about:settings.
Custom engines will be displayed below the builtin engines in the drop-
down to select the default engine.

A couple of edge cases here:

1. We currently reject a custom engine if one with the same name already
   exists. In the future, we should allow editing custom engines.

2. If a custom engine which was the default engine is removed, we will
   disable search rather than falling back to any other engine.
2025-04-06 13:45:10 +02:00
Timothy Flynn
dbf4b189a4 LibWebView: Do not use AK::format to format search engine URLs
This is to prepare for custom search engines. If we use AK::format, it
would be trivial for a user (or bad actor) to come up with a template
search engine URL that ultimately crashes the browser due to internal
assertions in AK::format. For example:

    https://example.com/crash={1}

Rather than coming up with a complicated pre-format validator, let's
just not use AK::format. Custom URLs will signify their template query
parameters with "%s". So we can do the same with our built-in engines.
When it comes time to format the URL, we will do a simple string
replacement.
2025-04-06 13:45:10 +02:00
Timothy Flynn
cbee476dac LibWebView: Store search engine names/URLs as String
In order to support custom search engines, we will need to store the
engine properties as String to hold user-provided data.

This also caused a compile error trying to assign Optional<SearchEngine>
to Optional<SearchEngine const&>, so there's a bit of extra churn here.
2025-04-06 13:45:10 +02:00
Timothy Flynn
7f37a8f60f AK: Add an AK::find helper to return a reference to the found value
This is often more convenient than dealing with iterators.

This commit includes a couple conversions to find_value as examples.
2025-04-06 13:45:10 +02:00
Timothy Flynn
9cab5dc0c9 Base: Consolidate a couple of about:settings container classes 2025-04-06 13:45:10 +02:00
Andreas Kling
d138474e0d LibJS: Avoid unnecessary shifts in Value empty/null/undefined checks
We know that the payload is always 0 for these three Value types, and so
we can implement checking for them as full 64-bit compares against
constant values instead of checking just the tag.

This avoids shifting the tag 48 bits to the right before comparing it.
Since these are used all over the place, it actually leads to a nice
code size reduction.
2025-04-06 04:47:01 +02:00
Andreas Kling
c8865458da LibJS: Mark exception-handling paths with [[unlikely]] in interpreter
This appears actually helpful and consistently makes all benchmarks
slightly faster on my machine.
2025-04-06 04:47:01 +02:00
Andreas Kling
aec7dd5778 LibJS: Mark Interpreter::handle_exception() as NEVER_INLINE
Before this change, we were inlining this function after every
handler for instructions that could throw.

Forcing it out-of-line shrinks the main bytecode interpreter by 15%
and yields a decent 2.5% speedup on JetStream/gcc-loops.cpp.js
2025-04-06 04:47:01 +02:00
Aliaksandr Kalenik
d5edd62e57 LibWeb: Limit usage of getElementById() cache to connected roots
Fixes bug when we always return null from getElementById() on
unconnected roots because id to element cache is only maintained for
connected roots.

Fixes broken Perf-Dashboard suite in Speedometer 3.
2025-04-06 04:14:29 +02:00
Andreas Kling
3c2a2bb39f LibJS: Shrink JS::Bytecode::Operand from 8 bytes to 4 bytes
This packs the bytecode much better and gives us a decent performance
boost on throughput-focused benchmarks.

Measured on my M3 MacBook Pro:
- 4.7% speedup on Kraken
- 2.3% speedup on Octane
- 2.7% speedup on JetStream1
2025-04-06 02:05:27 +02:00
Andreas Kling
70411a117b LibJS: Use u32 instead of size_t for bytecode instruction array sizes
Instructions that have an embedded tail array are not going to have
more than 2^32 elements in any remotely sane situation.
2025-04-06 02:05:27 +02:00
Andreas Kling
42cc481091 LibJS: Make Optional<StringTableIndex> use less space
We can use the index's invalid state to signal an empty optional.
This makes Optional<StringTableIndex> 4 bytes instead of 8,
shrinking every bytecode instruction that uses these.
2025-04-06 02:05:27 +02:00
Andreas Kling
f1a54ef281 LibJS: Use u32 for RegexTableIndex
Same as we already do for StringTableIndex and IdentifierTableIndex.
2025-04-06 02:05:27 +02:00
rmg-x
37998895d8 AK+Meta+LibCore+Tests: Remove unused SipHash implementation
This is a homegrown implementation that wasn't actually used in
dependent classes. If this is needed in the future, using OpenSSL would
probably be a better option.
2025-04-06 01:47:50 +02:00
Timothy Flynn
f1f7f68f36 LibWebView: Highlight about: and data: URL schemes 2025-04-06 00:32:14 +02:00
Aliaksandr Kalenik
c3121c9d8a LibIPC+Meta: Keep message buffer alive until acknowledged by peer
This change ensures that instead of immediately deallocating the message
buffer after sending, we retain it in an acknowledgement wait queue
until an acknowledgement is received from the peer. This is necessary
to handle a behavior of the macOS kernel, which may prematurely
garbage-collect file descriptors contained within the message buffer
before the peer receives them.

The acknowledgement mechanism assumes messages are received in the same
order they were sent so, each acknowledgement message simply indicates
the count of successfully received messages, specifying how many entries
can safely be removed from the acknowledgement wait queue.
2025-04-05 23:14:32 +02:00
Andreas Kling
15e2c78e9a LibJS: Shrink ThrowCompletionOr<void>
By specializing this template and using the special empty JS::Value as a
marker for the `void` state, we shrink this very common class from 16
bytes to 8 bytes.

This allows bytecode instruction handlers to return their result in a
single 64-bit register, allowing tighter code generation.
2025-04-05 21:34:13 +02:00
Andreas Kling
c5a239b8c4 LibJS: Add missing visit for CyclicModule::m_evaluation_error 2025-04-05 21:34:13 +02:00
Lukas Scheller
852e8ff12f LibWeb: Fix grid placement with named lines 2025-04-05 21:30:37 +02:00
devgianlu
6fc9de7aab LibJS: Remove invalid call to realm() on bytecode generator error
There is no realm when that call happens, use the same logic as the
lines above to create an error from the VM alone.
2025-04-05 20:55:21 +02:00
rmg-x
27c19c02d2 RequestServer: Remove check for square brackets in host before resolving
This is no longer needed since `IPv6Address::from_string` supports
square brackets. After the update to curl, `CURLOPT_RESOLVE` now
supports replacing IPv6 hosts as well.
2025-04-05 14:26:09 -04:00
rmg-x
6480e1a3fe AK+Tests: Add support for URI syntax in IPv6Address::from_string
This supports IPv6 strings that start with `[` and end with `]` in
accordance with RFC3986 which states:

A host identified by an Internet Protocol literal address, version 6
[RFC3513] or later, is distinguished by enclosing the IP literal
within square brackets ("[" and "]").  This is the only place where
square bracket characters are allowed in the URI syntax.
2025-04-05 14:26:09 -04:00
rmg-x
20e6de9340 Meta: Update curl to 8.13.0 2025-04-05 14:26:09 -04:00
devgianlu
08cfd5ff1b LibJS: Set empty function parameters on ClassStaticInit scope
This prevents the variables declared inside a class static initializer
to escape to the nearest containing function causing all sorts of memory
corruptions.
2025-04-05 18:20:36 +01:00
devgianlu
6aea459e00 LibJS: Wrap static_init_block_scope call in its own scope 2025-04-05 18:20:36 +01:00
Ali Mohammad Pur
396f35c41d Meta: Don't require LTO to build in release mode
check_ipo_supported() will by default fail the generation if IPO is not
available; this commit makes it so we continue the build just without
LTO.
2025-04-05 19:09:59 +02:00
Andreas Kling
fe1962d7fa LibJS: Make SetCompletionType bytecode instruction actually set type
This recovers 38 tests in test262 that regressed in a0bb31f7a0.
2025-04-05 15:00:05 +02:00
Tim Ledbetter
026bc91d6c LibWeb/CSS: Extract border width values directly
There's no need to keep a copy of a `BorderData` object in this case.
This makes the variable names used a bit less confusing.
2025-04-05 12:54:22 +02:00
Tim Ledbetter
32812f5db0 LibWeb: Return absolutized computed value for outline width property 2025-04-05 12:54:22 +02:00
Andreas Kling
b05b9378ed LibJS: Demote VERIFYs in Completion() to ASSERT
These were *extremely* hot in profiles (noticed when looking at
disassembly).

Now that we've made the special empty JS::Value much harder to create
accidentally, we can feel better about turning these into ASSERT and
catching them in debug builds.
2025-04-05 11:20:26 +02:00
Andreas Kling
3cf50539ec LibJS: Make Value() default-construct the undefined value
The special empty value (that we use for array holes, Optional<Value>
when empty and a few other other placeholder/sentinel tasks) still
exists, but you now create one via JS::js_special_empty_value() and
check for it with Value::is_special_empty_value().

The main idea here is to make it very unlikely to accidentally create an
unexpected special empty value.
2025-04-05 11:20:26 +02:00
Andreas Kling
0d91363742 LibJS: Remove weird fallback behavior in VM::argument/argument_count
If there's no running execution context, let's just error out in there
instead of returning a weird empty value.
2025-04-05 11:20:26 +02:00
Andreas Kling
ceddc8d660 LibJS: Make a bunch of functions in Environment pure virtual 2025-04-05 11:20:26 +02:00
Andreas Kling
de424d6879 LibJS: Make Completion.[[Value]] non-optional
Instead, just use js_undefined() whenever the [[Value]] field is unused.
This avoids a whole bunch of presence checks.
2025-04-05 11:20:26 +02:00
Andreas Kling
c0600c4353 LibJS: Remove unused ThrowCompletionOr<T>::release... helper 2025-04-05 11:20:26 +02:00
Andreas Kling
6d8bc2b1d6 LibJS: Remove unused Completion::update_empty() 2025-04-05 11:20:26 +02:00
Andreas Kling
41314d0460 LibJS: Remove unnecessary exception checks in bytecode dispatch
No need to check for exceptions after instructions that cannot throw.
2025-04-05 11:20:26 +02:00
Tim Ledbetter
8738987e44 LibWeb: Return absolutized computed value for border width properties 2025-04-04 23:45:06 +02:00
Andrew Kaster
743f8a3a0a CMake: Add macro to wrap C++ command line definitions for swiftc
Similar to the existing macros for compile options and link options,
this macro wraps the command line definitions for swiftc in a way that
avoids warnings about conditional compilation flags not having values.
2025-04-04 13:06:53 -06:00
Andrew Kaster
8fd81c3338 LibGC+LibWeb+LibJS: Remove workaround for Swift boolean bitfield issue
We're using a main snapshot everywhere, so we can yeet the workaround.
2025-04-04 13:06:53 -06:00
Tim Ledbetter
e73438e82c LibWeb: Clamp grayscale, invert, filter and opacity filter values to 1 2025-04-04 17:12:47 +01:00
Tim Ledbetter
e5f21b2f9c LibWeb: Set blur filter radius to 0px if omitted 2025-04-04 17:12:47 +01:00
Tim Ledbetter
2ee86d1e18 LibWeb: Set hue-rotate angle to 0 degrees if omitted 2025-04-04 17:12:47 +01:00
Tim Ledbetter
61f76c7ec5 LibWeb: Set color filter value to 1 if omitted 2025-04-04 17:12:47 +01:00
Tim Ledbetter
46411295d6 LibWeb: Serialize drop-shadow filter properties in canonical order 2025-04-04 17:12:47 +01:00
Jess
83e46b3728 LibRegex: Fix crash when parse result exceeds max cache size
Before, If the cache was empty we would try and evict non-existant
entries and crash. So the fix is to make sure that we don't saturate
the cache with a single parse result.
2025-04-04 16:10:25 +02:00
Jelle Raaijmakers
99df80f81e LibWeb: Only apply box offset if the box is not already the ancestor
When determining the content/margin box rects within their ancestor's
coordinate space, we were returning early if the passed in values
already belonged to the requested ancestor. Unfortunately, we had
already applied the used values' offset to the rect, which is the offset
to the ancestor's ancestor.

This simplifies the logic to always apply the rect offset after checking
if we've reached the ancestor. Fixes determining float intrusions inside
block elements with `margin: auto` set.

Fixes #4083.
2025-04-04 15:35:26 +02:00
R-Goc
28d5d982ce Everywhere: Remove unused private fields
This commit removes the -Wno-unusued-private-field flag, thus
reenabling the warning. Unused field were either removed or marked
[[maybe_unused]] when unsure.
2025-04-04 12:40:07 +02:00
Sam Atkins
e43bb1410c LibWeb/CSS: Reject non-grouping-rules as descendants of style rules
For example, `@font-face` is not only invalid inside a style rule, it's
also invalid inside a child of a style rule. This fixes a test
regression that we previously passed by accident.
2025-04-04 10:40:32 +01:00
Sam Atkins
9cce791424 LibWeb/CSS: Only attempt to load valid @font-face fonts
These must have a `font-family` and `src` set to be included in
font-matching. Otherwise they should be ignored, but still exist in the
CSSOM.
2025-04-04 10:40:32 +01:00
Sam Atkins
f87b454fa9 LibWeb/CSS: Parse @font-face descriptors as style values
CSSFontFaceRule now stores its values as a CSSFontFaceDescriptors, with
a ParsedFontFace produced on request. This is exposed via the `style`
attribute, so we pass a lot of tests that try to read values from
that.

We have one test regression, which we passed by mistake before: The test
wanted to ensure we don't allow `@font-face` nested inside other rules.
We passed it just because we discarded any `@font-face` without a
`font-family`. What we're supposed to do is 1) keep at-rules with
missing required descriptors and just not use them, and 2) reject
certain ones when nested.

We may want to cache the ParsedFontFace in the future, but I didn't here
because 1) it's called rarely, and 2) that would mean knowing to
invalidate it when the CSSFontFaceDescriptors changes, which isn't
obvious to me right now.
2025-04-04 10:40:32 +01:00
Sam Atkins
3c9685ff1a LibWeb/CSS: Support creating ParsedFontFace from CSSFontFaceDescriptors 2025-04-04 10:40:32 +01:00
Sam Atkins
cb8511772d LibWeb/CSS: Add CSSFontFaceDescriptors type
This is a CSSOM type that holds the descriptors for a CSSFontFaceRule,
but this commit only adds it without using it.
2025-04-04 10:40:32 +01:00
Sam Atkins
1bc73ed4a8 LibWeb/CSS: Add missing include to StringStyleValue.h 2025-04-04 10:40:32 +01:00
Sam Atkins
fd45c53c11 LibWeb: Parse descriptors as style values, using the JSON data
The goal here is to do something a bit smarter with the parsing here
than we do for properties. Instead of the JSON saying "here are the
values, and here are the keywords, and we can have up to 3", here we
place the syntax in the JSON directly (though currently broken up as
one string per option) and then we attempt to parse each one in
sequence. It's something we'll need eventually for `@property` among
other things.

...However, in this first pass, I've gone with the simplest option of
hard-coding the types instead of figuring them out properly. So there's
a PositivePercentage type and a UnicodeRangeTokens type, instead of
properly implementing the grammar for those in a generic way.
2025-04-04 10:40:32 +01:00
Sam Atkins
60c536bdd5 LibWeb/CSS: Add FontSourceStyleValue
This will be used by the `@font { src: ... }` descriptor once we parse
descriptors as style values.
2025-04-04 10:40:32 +01:00
Sam Atkins
79093291b5 LibWeb/CSS: Un-template parse_comma_separated_value_list()
This doesn't need to be a template. Changing it means we can use it from
any FooParsing.cpp file, and also move it ValueParsing.cpp where it
belongs.
2025-04-04 10:40:32 +01:00
Sam Atkins
fd4f4f425d LibWeb: Generate DescriptorID enum
Add a new JSON file describing at-rule descriptors, and then use it to
generate a DescriptorID enum, and code to check if it's accepted in a
given at-rule.
2025-04-04 10:40:32 +01:00
Timothy Flynn
a3ea4881e7 LibWeb+LibWebView+UI: Migrate to LibWebView's language settings 2025-04-04 10:16:32 +02:00
Timothy Flynn
f242920cc9 LibWebView: Add language settings to about:settings
This implements a setting to change the languages provided to websites
from `navigator.language(s)` and the `Accept-Language` header. Whereas
the existing Qt settings dialog allows users to type their language of
choice, this setting allows users to select from a predefined list of
languages. They may choose any number of languages and their preferred
order.

This patch only implements the persisted settings and their UI. It does
not integrate the choses languages into the WebContent process.
2025-04-04 10:16:32 +02:00
Timothy Flynn
26ec01068f LibWebView: Fire all observers when settings are restored to default
Otherwise the change is not propagated to the WebContent process for
some of these.
2025-04-04 10:16:32 +02:00
Timothy Flynn
aad95d8d9d Base: Generalize some about:settings CSS classes
The dialog classes here have specific names that will be used in another
dialog. This patch renames them to be more generic. And moves a border
style to not assume a dialog-footer element will exist.
2025-04-04 10:16:32 +02:00
Timothy Flynn
c8d6890ba2 Base: Write "websites" as a single word on about:settings
Although "web site" was originally two words, it is now canonically one
word.
2025-04-04 10:16:32 +02:00
Tim Ledbetter
c941170e5a LibWeb: Invalidate document style when media rules are changed
This ensures that new media rules are always produce the correct result
when evaluated.
2025-04-04 10:10:43 +02:00
Tim Ledbetter
1659381362 Meta: Download WPT support files used in iframes 2025-04-04 10:10:43 +02:00
R-Goc
8f1a7934e1 WebContent: Remove unused private member
This commit removes the unused m_heap member from ConnectionFromClient.
This also works around an issue where some cmake version doesn't apply
compiler options from within a subdirectory globally.
2025-04-04 10:09:37 +02:00
Andrew Kaster
67848a8c51 CI: Add nightly Swift jobs for both Linux and macOS 2025-04-03 16:47:48 -06:00
Andrew Kaster
382b574946 CI: Rework Swift build to be a separate job from normal macOS builds 2025-04-03 16:47:48 -06:00
Andrew Kaster
345cd6b9c9 CI: Add setup steps to install swift toolchain from swiftly
Now that swiftly 1.0.0 is available, we can use it to install main
snapshot toolchains on both Linux and macOS.
2025-04-03 16:47:48 -06:00
Andrew Kaster
195f0106a4 Meta: Add swiftly .swift-version to .gitignore 2025-04-03 16:47:48 -06:00
Andrew Kaster
1ed4e64575 CMake: Refactor FindSwiftTesting to find TestingMacros dir on macOS
Turns out we need this directory to pass to the -frontend command
for creating the interop header, so refactor the whole find module
to find it on each platform.
2025-04-03 16:47:48 -06:00
Andrew Kaster
9ee2473aa4 LibWeb+LibGC: Import GC swift module into LibWeb and an initial user
Start work on a speculative HTML Parser in Swift. This component will
walk ahead of the normal HTML parser looking for fetch() requests to
make while the normal parser is blocked. This work exposed many holes in
the Swift C++ interop component, which have been reported upstream.
2025-04-03 16:47:48 -06:00
Andrew Kaster
8554ee386e LibGC: Teach Swift bindings about Cell and Cell::Visitor
Add the proper annotations for the Cell and Cell::Visitor classes to be
visible in Swift. This lets us remove some OpaquePointer shinangians in
the Swift bindings.
2025-04-03 16:47:48 -06:00
Andrew Kaster
4ab89d8bbb AK: Add cxxCast template to allow Swift to perform simple checked casts
This is a workaround for the lack of support for imported class
hierarchies in Swift. Swift's ClangImporter doesn't tell the Swift
frontend about derived class relationships between imported types.
2025-04-03 16:47:48 -06:00
Andrew Kaster
e4c88915ab LibGC+LibJS+LibWeb: Add workaround for Swift boolean bitfield issue
This patch adds a workaround for a Swift issue where boolean bitfields
with getters and setters in SWIFT_UNSAFE_REFERENCE types are improperly
imported, causing an ICE.
2025-04-03 16:47:48 -06:00
Andrew Kaster
08b27f7b6e AK: Mark Function as SWIFT_UNSAFE_REFERENCE
This allows us to import APIs that include a function without crashing
the frontend. Without this, it chokes on the move-only behavior of the
class.
2025-04-03 16:47:48 -06:00
Andrew Kaster
c85043f2e1 CI: Bump CI Xcode version to 16.2 2025-04-03 16:47:48 -06:00
Timothy Flynn
d403f02988 AK: Remove unused capacity field from StringData
This was added to be used with `kfree_sized` when we construct a String
from a StringBuilder. As of 53cac71cec, it
is unused, causing some compilers to raise a warning.

This reduces the size of StringData from 24 to 16 bytes.
2025-04-03 23:44:40 +02:00
Aliaksandr Kalenik
12a2aebeb6 LibWeb: Move painting surface allocation into rendering thread
Skia has a check in debug mode to verify that surface is only used
within one thread. Before this change we were violating this by
allocating surfaces on the main thread while using and destructing them
on the rendering thread.
2025-04-03 22:01:43 +02:00
Andreas Kling
3169747989 LibJS: Emit PutById instead of PutByValue when key is string literal
Basically convert o["foo"]=x into o.foo=x when emitting bytecode.
These are effectively the same thing, and the latter format opts
into using an inline cache for the property lookups.
2025-04-03 18:47:38 +02:00
Andreas Kling
4426c50a18 LibJS: Emit GetById instead of GetByValue when key is string literal
Basically convert o["foo"] into o.foo when emitting bytecode. These are
effectively the same thing, and the latter format opts into using an
inline cache for the property lookups.
2025-04-03 18:47:38 +02:00
Andreas Kling
976ccb9224 LibJS: Add fast path for Int32 values in ToBoolean
It's not uncommon to branch on the boolean value of integers,
so let's do that on the ToBoolean fast path.
2025-04-03 18:47:38 +02:00
Andreas Kling
8de03e8cfd LibJS: Add fast paths in ToNumeric for booleans, null and undefined
These are still in the out-of-line "slow path" for ToNumeric, but
skipping all the coercion machinery can save us a lot of time.
2025-04-03 18:47:38 +02:00
Andrew Kaster
3fcef0c519 Revert "CI: Temporarily install CMake 3.x"
This reverts commit c5c3859205.
2025-04-03 08:03:48 -06:00
Andrew Kaster
20352cc05b Meta: Update vcpkg to latest main revision
This should resolve CMake 4.0 issues on macOS using the fix upstream
vcpkg came up with.
2025-04-03 08:03:48 -06:00
Andrew Kaster
91c1aed57f Revert "Meta: Add workaround for CMake 4.0 policy minimum changes"
This reverts commit 04d44c9b26.
2025-04-03 08:03:48 -06:00
Andreas Kling
cba80580e2 Revert "LibJS: Avoid calling generic Instruction::length() during dispatch"
This reverts commit 8f2ee01e6f.

Speculative revert, as this appears to severely regress performance on
our JS benchmark runner.
2025-04-03 15:09:49 +02:00
Andreas Kling
ec590ef3e6 LibJS: Add builtin for Math.random() 2025-04-03 13:56:39 +02:00
Andreas Kling
714e8aec8a LibJS: Add builtin for Math.imul() 2025-04-03 13:56:39 +02:00
Andreas Kling
ab5d5d8b50 LibGC: Avoid excessive bitfield use in GC::Cell
We didn't actually save any space by making the Cell flags bitfields.
In fact, it just forced us to do bit twiddling when accessing them.
2025-04-03 13:56:39 +02:00
Andreas Kling
8f2ee01e6f LibJS: Avoid calling generic Instruction::length() during dispatch
Since we know the exact type, we can avoid calling the generic lookup
function that branches on instruction type.
2025-04-03 13:56:39 +02:00
Aliaksandr Kalenik
4b04e97feb LibWeb: Send IPC messages exceeding socket buffer through shared memory
It turned out that some web applications want to send fairly large
messages to WebWorker through IPC (for example, MapLibre GL sends
~1200KiB), which led to failures (at least on macOS) because buffer size
of TransportSocket is limited to 128KiB. This change solves the problem
by wrapping messages that exceed socket buffer size into another message
that holds wrapped message content in shared memory.

Co-Authored-By: Luke Wilde <luke@ladybird.org>
2025-04-03 13:55:41 +02:00
Aliaksandr Kalenik
bc0ec84100 LibWeb: Don't queue rendering task for empty display lists 2025-04-02 23:22:38 +02:00
Aliaksandr Kalenik
cf143cf118 LibWeb: Don't call flush() when no surface is passed in execute_impl()
`DisplayListPlayer::execute_impl()` can receive null surface if it was
invoked to rasterize nested display lists (we use them for iframes). In
this case we should not call `flush()` by the end of execution and wait
until outer display list execution will do that.
2025-04-02 23:22:38 +02:00
Timothy Flynn
920170f60a LibWebView+UI: Remove native do-not-track setting 2025-04-02 14:16:18 -04:00
Timothy Flynn
1be3e7fd8a LibWebView: Add do-not-track setting to about:settings 2025-04-02 14:16:18 -04:00
Timothy Flynn
49dae536a7 Base: Replace bespoke input switch with native element
Turns out we support <input type=checkbox switch>, so let's use it!
2025-04-02 14:16:18 -04:00
Andrew Kaster
04d44c9b26 Meta: Add workaround for CMake 4.0 policy minimum changes
In CMake 4.0, having a minimum policy version set to less than 3.5 is
a hard error at configure time. Add an override until the issue can be
resolved in vcpkg itself.
2025-04-02 10:50:18 -06:00
Andrew Kaster
8e0786641f Meta: Explicitly enable zstd feature for tiff in vcpkg
Without this, the library was pulling system libzstd implicitly.
2025-04-02 10:50:18 -06:00
Andrew Kaster
6c0f97dcf2 Meta: Omit vcpkg overlay ports from style and EOF lints 2025-04-02 10:50:18 -06:00
Andrew Kaster
8455d23a4b Revert "Meta: Add fontconfig and freetype vcpkg overlays"
This reverts commit 20890d7b70.

The maintenance and downtime for the freedesktop GitLab is resolved.
2025-04-02 10:50:18 -06:00
Andrew Kaster
1fec9d6917 Meta: Update vcpkg to latest master
This includes some fixes for cmake 4.0, but not all.
2025-04-02 10:50:18 -06:00
Sam Atkins
3af25b9d2f LibWeb/SVG: Mark SVG factory functions as [NewObject]
Corresponds to 9991813a66
2025-04-02 17:28:45 +01:00
Sam Atkins
b74ec1ab7e LibWeb/SVG: Remove fixme about SVGSVGElement::getElementById()
Resolved in e02e2c6465
2025-04-02 17:28:45 +01:00
Sam Atkins
07adbddbcd LibWeb/SVG: Remove SVGAElement.text attribute
Corresponds to 7210af6604
2025-04-02 17:28:45 +01:00
Sam Atkins
02e8c0e1d1 LibWeb/HTML: Allow throwing SecurityError for push/replaceState() abuse
Corresponds to 73e51b414b
2025-04-02 17:28:06 +01:00
Sam Atkins
7367150536 LibWeb/HTML: Update FIXME to not reset form-associated custom elements
Corresponds to e6bdd0557a
2025-04-02 17:28:06 +01:00
R-Goc
5226a566e9 AK: Modify IntrusiveRedBlackTree for Windows
IntrusiveRedBlackTree relies on a member pointer for accessing the value
of a node. On windows member pointers can be of variable length,
depending on the inheritance structure of the class. This commit casts
the 4 byte member pointer, or rather offset to a full pointer type, so
that the bit_cast to u8* works, as previously the source was smaller
than the destination, which fails inside __builtin_bit_cast().
2025-04-02 10:22:08 -06:00
Timothy Flynn
e879fd29b3 Base: Use correct color code for Slate Blue 100 2025-04-02 11:41:01 -04:00
Sam Atkins
405785f584 Tests: Disable 3 tests that are flaky on CI 2025-04-02 16:08:53 +01:00
Sam Atkins
86b57a5205 LibWeb/CSS: Use font_format_is_supported() when parsing font sources 2025-04-02 15:53:50 +01:00
Sam Atkins
bd7a08da3b Tests: Reimport font-stretch tests as font-width
Corresponds to 7c0c4806bb
2025-04-02 14:55:27 +01:00
Tim Ledbetter
cbb169820a LibWeb/CSS: Implement the CSSImportRule.media attribute 2025-04-02 13:53:03 +01:00
Tim Ledbetter
b93d2b7be2 IDLGenerators: Don't attempt to set null [PutForwards] attribute
Previously, attempting to set a `[PutForwards]` annotated attribute,
would crash if the associated getter returned null.
2025-04-02 13:53:03 +01:00
Tim Ledbetter
ac19b0cda8 LibWeb/CSS: Support media queries in import at-rules 2025-04-02 13:53:03 +01:00
Timothy Flynn
c1fe912bf9 UI/AppKit: Implement an autocomplete view for the location bar 2025-04-02 08:52:45 -04:00
Timothy Flynn
60dd5cc4ef UI/Qt: Migrate to LibWebView's autocomplete engine
As a result, we now no longer depend on Qt::Network.
2025-04-02 08:52:45 -04:00
Timothy Flynn
a87c264088 UI/Qt: Add a couple of missing includes
These are currently being transitively included. This will no longer be
the case in a future patch.
2025-04-02 08:52:45 -04:00
Timothy Flynn
5d2e6ffe30 LibWebView: Add autocomplete settings to about:settings
This implements an autocomplete engine inside LibWebView, to replace the
engine currently used by Qt. Whereas Qt uses the Qt Network framework to
perform autocomplete requests, LibWebView uses RequestServer. This moves
downloading this untrusted data out of the browser process.

This patch only implements the persisted settings and their UI. It does
not integrate this engine into the browser UI.
2025-04-02 08:52:45 -04:00
Timothy Flynn
92e1d297be LibRequests: Protect Request callbacks against stopped requests
When the request is stopped, we clear its internal stream data. There is
a window where RequestServer may have sent an IPC message whose callback
will try to access that data in the time between the data being cleared
and RS receiving the stop signal. When this happens, just bail from IPC.
2025-04-02 08:52:45 -04:00
Timothy Flynn
0de017df9b LibRequests: Move NetworkError stringification to LibRequests
Let's also rename the file to NetworkError.h while we're here. No need
to have "Enum" in the name.
2025-04-02 08:52:45 -04:00
Shannon Booth
a5df972055 LibWeb: Do not store network errors as a StringView
This is very clearly a very dangerous API to have, and was causing
a crash on Linux as a result of a stack use-after-free when visiting
https://www.index.hr/.

Fixes #3901
2025-04-02 11:43:53 +02:00
Kenneth Myhra
82a2ae99c8 Everywhere: Remove DeprecatedFlyString + any remaining references to it
This reverts commit 7c32d1e8a5.
2025-04-02 11:43:13 +02:00
Ali Mohammad Pur
4136d8d13e LibRegex: Use an interned string table for capture group names
This avoids messing around with unsafe string pointers and removes the
only non-FlyString-able user of DeprecatedFlyString.
2025-04-02 11:43:13 +02:00
Andreas Kling
6bb0d585e3 LibJS: Elide function wrapper for class field literal initializers
If a class field initializer is just a simple literal, we can skip
creating (and calling) a wrapper function for it entirely.

1.44x speedup on JetStream3/raytrace-private-class-fields.js
1.53x speedup on JetStream3/raytrace-public-class-fields.js
2025-04-01 23:55:20 +02:00
Aliaksandr Kalenik
fd147e6be0 LibWeb: Protect SkiaBackendContext with a mutex
The Skia Ganesh backend we currently use doesn't support painting from
multiple threads, which could happen before this change when the main
thread used Skia to paint on the HTML canvas while the rendering thread
was working on display list rasterization.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4172
2025-04-01 23:39:05 +02:00
Aliaksandr Kalenik
24527b6ae3 LibWeb: Pass PaintingSurface into DisplayListPlayer::execute()
Deleteing set_surface() makes DisplayListPlayer API a bit more intuitive
because now caller doesn't have to think whether it's necessary to
restore previous surface after execution, instead DisplayListPlayer
takes care of it by maintaining a stack of surfaces.
2025-04-01 23:39:05 +02:00
Timothy Flynn
b23b21fa4a UI/AppKit: Restore custom cursor shown on link hover
This seems to have broken in some recent-ish AppKit update. When we add
the status label to the view hierarchy / change its visibility state,
the NSApp is resetting the cursor to the standard cursor. By overriding
the cursorUpdate method to do nothing, we prevent this from happening.
2025-04-01 23:10:14 +02:00
Timothy Flynn
b64d450f32 CI: Set correct architecture for JS artifact builds 2025-04-01 16:49:28 -04:00
Timothy Flynn
c5c3859205 CI: Temporarily install CMake 3.x
Many vcpkg dependencies do not work with CMake 4.x, which GitHub Actions
now bundles by default. Install the latest 3.x from Kitware for now.
2025-04-01 20:49:03 +02:00
Andreas Kling
fd0a0e963a LibJS: Make IteratorRecord slightly smaller
By reordering the members, we take this from 40 bytes to 32 bytes.
2025-04-01 20:16:39 +02:00
Jelle Raaijmakers
23f0fddeab LibWeb: Let LineBuilder decide on Y-coordinate for float insertion
Instead of reaching into the IFC of the LineBuilder from the BFC, we
should let LineBuilder determine how to deal with the running vertical
float clearance. No functional changes.
2025-04-01 16:02:53 +02:00
Jelle Raaijmakers
6d911a6baa LibWeb: Resolve block height correctly after line break with clear: ..
If a block with inline children ends with a line break clearing any
floats, we not only need to take the introduced clearance into account
for the next line box, but the containing block needs to set the correct
height as well.

Since the spec calls for using the last line box' bottom as the resolved
height (if treated as auto), we now correctly apply the clearance to the
previous line box' bottom coordinate.

Fixes #4058.
2025-04-01 16:02:53 +02:00
Andreas Kling
e5db913b0d Revert "LibRegex: Port remaining DeprecatedFlyString to ByteString"
This reverts commit aab3fbe254.

Greatly regressed JavaScript benchmark performance.
2025-04-01 15:40:38 +02:00
Andreas Kling
7c32d1e8a5 Revert "Everywhere: Remove DeprecatedFlyString + any remaining references to it"
This reverts commit 3131e6369f.

Greatly regressed JavaScript benchmark performance.
2025-04-01 15:40:27 +02:00
Jelle Raaijmakers
45905d6f7b LibWeb: Use relative coordinates for available_space_for_line()
We were accidentally providing it with absolute Y-coordinates, messing
up stacked floating boxes that would otherwise intrude on each other.

Fixes #4160.
2025-04-01 15:26:12 +02:00
Jelle Raaijmakers
a728d67ac2 LibWeb: Only calculate float intrusions for definite available width
No functional changes.
2025-04-01 15:26:12 +02:00
Andreas Kling
b9c57d3122 LibJS: Use xorshift128++ PRNG for Math.random()
This is the same PRNG used by major browser engines, and although it's
a step down in randomness, it massively improves performance of
Math.random().

1.20x speedup on JetStream3/sync-file-system.js :^)
2025-04-01 15:16:54 +02:00
Jelle Raaijmakers
3bc6870bbf Meta: Make the "Release" build type use -O3 and -flto
This doesn't affect the default preset, but the Distribution preset will
now compile with these flags instead.
2025-04-01 13:44:05 +02:00
Glenn Skrzypczak
da09608156 LibWeb/Painting: Fix blending with viewport background
The viewport is now drawn onto transparent black instead of the
background color of the viewport.
2025-04-01 13:38:00 +02:00
Glenn Skrzypczak
9973b01848 LibWeb/CSS: Improved implementation of background-blend-mode
This is a improved version of a73cd88f0c
The old commit was reverted in 552dd18696

The new version only paints an element into a new layer if background
blend modes other than normal are used. The rasterization performance
of most websites should therefore not suffer.

Co-Authored-By: Alexander Kalenik <kalenik.aliaksandr@gmail.com>
2025-04-01 13:38:00 +02:00
Glenn Skrzypczak
6906f1722a LibWeb/Painting: Add back SaveLayer command
This reverts commit 552dd18696.
2025-04-01 13:38:00 +02:00
Kenneth Myhra
3131e6369f Everywhere: Remove DeprecatedFlyString + any remaining references to it 2025-04-01 12:50:00 +02:00
Kenneth Myhra
aab3fbe254 LibRegex: Port remaining DeprecatedFlyString to ByteString 2025-04-01 12:50:00 +02:00
Aliaksandr Kalenik
cb722ca18b LibWeb: Allow working on N+1 frame while N is rasterizing
This change allows us to overlap rasterization and rendering work across
threads: while the rasterization thread processes frame N, the main
thread can simultaneously work on producing the display list for frame
N+1.
2025-04-01 12:17:52 +02:00
Aliaksandr Kalenik
7248748157 Tests: Disable WebAnimations/animation-methods/updatePlaybackRate.html
This test is timing-sensitive, similar to some other animation tests we
had to disable, and starts failing on CI after the change in upcoming
commit, so let's disable it for now.
2025-04-01 12:17:52 +02:00
Luke Wilde
278666edcd LibWeb: Enforce Content Security Policy on navigation request/response 2025-04-01 04:01:28 +02:00
Timothy Flynn
004173f88b LibWeb: Allow parsing of "file" prompt types in WebDriver
See: https://github.com/w3c/webdriver/commit/3055808

This isn't actually used outside of BiDi.
2025-04-01 03:52:02 +02:00
Timothy Flynn
952ad4e68b LibWeb: Allow fractional numbers for WebDriver mouse-move coordinates
See: https://github.com/w3c/webdriver/commit/a67669c
2025-04-01 03:52:02 +02:00
Luke Wilde
ee6dbcc96e LibWeb: Apply HTMLFontElement's face attribute's presentational hint
Fixes font selection on https://stagsnet.net/
2025-04-01 03:50:30 +02:00
Aliaksandr Kalenik
e33174fca1 LibWeb: Make BackingStore atomic ref-counted
This is required to make sure rendering thread will keep backing stores
alive in case backing stores reallocation happens during rasterization.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4164
2025-04-01 03:05:21 +02:00
Andreas Kling
a0bb31f7a0 LibJS: Make async functions & generators faster with helper types
Instead of returning internal generator results as ordinary JS::Objects
with properties, we now use GeneratorResult and CompletionCell which
both inherit from Cell directly and allow efficient access to state.

1.59x speedup on JetStream3/lazy-collections.js :^)
2025-04-01 02:30:42 +02:00
Glenn Skrzypczak
1022566bff LibWeb/Layout: Properly remove layout nodes
This properly remove the old layout node subtree when no new layout
node is created during layout update.
2025-03-31 18:19:58 +01:00
Aliaksandr Kalenik
24e2c402f5 LibWeb+WebContent: Move display list rasterization off the main thread
The display list is an immutable data structure, so once it's created,
rasterization can be moved to a separate thread. This allows more room
for performing other tasks between processing HTML rendering tasks.

This change makes PaintingSurface, ImmutableBitmap, and GlyphRun atomic
ref-counted, as they are shared between the main and rendering threads
by being included in the display list.
2025-03-31 15:58:15 +01:00
Jelle Raaijmakers
86b831750d LibWeb: Layout children a bit earlier in BlockFormattingContext
We don't need to duplicate this piece of code. No functional changes.
2025-03-31 08:11:10 +01:00
Jelle Raaijmakers
04ba375cc7 LibWeb: Only set line builder's block offset if clearance increases it
This prevents text from overlapping with each other if a `<br>` with
`clear: ..` is used in between.
2025-03-31 08:11:10 +01:00
Timothy Flynn
6f1710121d LibWeb: Remove OOM handling from the AutoplayAllowlist 2025-03-30 16:18:57 +01:00
Timothy Flynn
ed265b568d LibWebView+WebContent+UI: Migrate to the new autoplay settings
This removes the old autoplay allowlist file in favor of the new site
setting. We still support the command-line flag to enable autoplay
globally, as this is needed for WPT.
2025-03-30 16:18:57 +01:00
Timothy Flynn
223b04f087 LibWebView: Add autoplay settings to about:settings
The idea with the UI here is that it will serve as a generic component
for all site settings, such as autoplay, notifications, etc. When the
site settings dialog is opened, it is filled with the requested setting
data, and messages sent to the browser process are based on the setting.

This patch only implements the UI and persisted settings. It does not
apply autoplay changes to the WebContent process.
2025-03-30 16:18:57 +01:00
Timothy Flynn
c7979a8bd6 LibWeb: Add missing forward-include to AutoplayAllowlist
This just lets clangd index this file.
2025-03-30 16:18:57 +01:00
Andreas Kling
4dc63ddf49 LibJS: Make Optional<Utf16String> use less space
By specializing the template, we can shrink it from 16 to 8 bytes.
This makes PrimitiveString a measly 32 bytes. :^)
2025-03-30 07:16:40 +01:00
Andreas Kling
152691f9eb LibWeb: Make RopeString subclass so PrimitiveString can be smaller
By moving the LHS and RHS pointers used by rope strings into a
RopeString subclass, we shrink PrimitiveString by 16 bytes. Most strings
are not rope strings, so this ends up saving quite a bit of memory.
2025-03-30 07:16:40 +01:00
Tim Ledbetter
568531f06a Everywhere: Mark GC::Cell derived classes as Weakable explicitly
Previously, all `GC::Cell` derived classes were Weakable. Marking only
those classes that require this functionality as Weakable allows us to
reduce the memory footprint of some frequently used classes.
2025-03-29 17:36:33 -05:00
Totto16
11280897d3 LibWeb: Add Extended Tests for Window BarProps
Add Tests for Window BarProps in popout windows
2025-03-29 02:35:27 +00:00
Totto16
b66e7ac1ba LibWeb: Implement BarProp properties for Window 2025-03-29 02:35:27 +00:00
Andreas Kling
ad634897b8 Tests: Hide scrollbars in failing ref test
The test scrolled-svg-path-with-transform.html was relying on overlay
scrollbars mistakenly not showing up.
2025-03-28 22:01:51 +00:00
Andreas Kling
ba8aabdeb0 Revert "LibWeb: Skip "overlay" paint phase when there's no inspected node"
This reverts commit dc56435ecd.

It broke overlay scrollbars.
2025-03-28 20:08:48 +00:00
Jelle Raaijmakers
b688fe0396 Tests: Update FileWatcher's test timeouts
Increase the step timeouts on Linux from 50 to 75 milliseconds, since
we're seeing the occasional timeout on CI. For macOS, we should probably
be able to execute the tests a bit quicker than 500ms per step.
2025-03-28 19:19:43 +00:00
Aliaksandr Kalenik
1229328adc Revert "LibWeb/Painting: Add SaveLayer command"
This reverts commit 1898643ba4.
2025-03-28 16:48:03 +00:00
Aliaksandr Kalenik
552dd18696 Revert "LibWeb/CSS: Implement 'background-blend-mode'"
This reverts commit a73cd88f0c.

Emitting SaveLayer for each paintable made rasterization a lot slower
on every website because now Skia has to allocate enormous amounts of
temporary surfaces. Let's revert it for now and figure how to implement
it with less aggressive SaveLayer usage.
2025-03-28 16:48:03 +00:00
Andreas Kling
2462a6b0fa LibJS: Use Value::to_byte_string() in fewer places 2025-03-28 12:31:40 -04:00
Andreas Kling
c71772126f LibJS: Remove ByteString internals from PrimitiveString
PrimitiveString is now internally either UTF-8, UTF-16, or both.
We no longer convert them to/from ByteString anywhere, nor does VM have
a ByteString cache.
2025-03-28 12:31:40 -04:00
Timothy Flynn
f05b0bfd5f LibWeb+LibWebView+WebContent: Convert about:settings to a WebUI 2025-03-28 07:31:10 -04:00
Timothy Flynn
c75e40180c LibWeb+LibWebView+WebContent: Convert about:processes to a WebUI 2025-03-28 07:31:10 -04:00
Timothy Flynn
41aeb9e63a LibWeb+LibWebView+WebContent: Introduce a WebUI framework
When we build internal pages (e.g. about:settings), there is currently
quite a lot of boilerplate needed to communicate between the browser and
the page. This includes creating IDL for the page and the IPC for every
message sent between the processes.

These internal pages are also special in that they have privileged
access to and control over the browser process.

The framework introduced here serves to ease the setup of new internal
pages and to reduce the access that WebContent processes have to the
browser process. WebUI pages can send requests to the browser process
via a `ladybird.sendMessage` API. Responses from the browser are passed
through a WebUIMessage event. So, for example, an internal page may:

    ladybird.sendMessage("getDataFor", { id: 123 });

    document.addEventListener("WebUIMessage", event => {
        if (event.name === "gotData") {
            console.assert(event.data.id === 123);
        }
    });

To handle these messages, we set up a new IPC connection between the
browser and WebContent processes. This connection is torn down when
the user navigates away from the internal page.
2025-03-28 07:31:10 -04:00
Lucien Fiorini
f72d87931f LibJS: Reduce Mov instructions by using preferred destinations 2025-03-28 11:21:12 +00:00
Lucien Fiorini
5707076b9e LibJS: Optimize away Mov instructions when the source is the destination 2025-03-28 11:21:12 +00:00
Sam Atkins
192cae17ee LibWeb/DOM: Update step 4 of load_document()
Corresponds to 2ab779b8e8

We don't implement most of what that touches, so the only actual change
is a couple of words added here.
2025-03-28 11:18:57 +00:00
Glenn Skrzypczak
a73cd88f0c LibWeb/CSS: Implement 'background-blend-mode'
This implements the 'background-blend-mode' CSS property.
2025-03-28 09:41:06 +00:00
Glenn Skrzypczak
1898643ba4 LibWeb/Painting: Add SaveLayer command
This adds a command for saving the current layer of the canvas.
This is useful for painting content onto a blank background in
isolation and later compositing it onto the canvas.
2025-03-28 09:41:06 +00:00
Glenn Skrzypczak
3e56e9e65d Tests: Import URLs surrounded by single quotes
This updates the regex for CSS URLs in the WPT import script to
correctly match URLs surrounded by single quotes.
2025-03-28 09:41:06 +00:00
Sam Atkins
09b8f73e11 LibWeb/CSS: Implement UnicodeRangeStyleValue
This is preparation for storing at-rule descriptors as style values.
2025-03-28 09:15:02 +00:00
Sam Atkins
e0a03147c6 LibGfx: Make UnicodeRange comparable 2025-03-28 09:15:02 +00:00
Sam Atkins
ef3a2bf907 LibWeb/CSS: Move functions for detecting var()/attr() into Token types
This makes them accessible outside of PropertyParsing.cpp (which will be
useful if/when descriptors can include them). I've also renamed them to
use the correct term: "arbitrary substitution function".
2025-03-28 09:15:02 +00:00
Aliaksandr Kalenik
732a5cdc12 LibWeb: Respect min/max-content available size in auto width calculation
...for block level boxes. Otherwise we end up resolving auto width as
zero during intrinsic layout, which leads to incorrectly applied
max-width constraint.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/4123
2025-03-28 02:13:41 +00:00
Jelle Raaijmakers
2794ed0c73 CI: Do not cancel in-progress JS artifact builds
It might be useful to have these artifacts, even for older commits. As
an added bonus, this causes the JS benchmarks to run as well giving us
more datapoints.
2025-03-27 23:58:21 +00:00
Luke Wilde
c7d25301d3 LibWeb: Implement the LegacyUnforgeable attribute
This fixes the frame-ancestors WPT tests from crashing when an iframe
is blocked from loading. This is because it would get an undefined
location.href from the cross-origin iframe, which causes a crash as it
expects it to be there.
2025-03-27 23:50:35 +00:00
Tim Ledbetter
7853b757c2 LibWeb: Lower the baseline of text with veritcal-align: sub
This lowers the baseline of the given text by one fifth of the parent's
font size.
2025-03-27 23:30:57 +00:00
Tim Ledbetter
6fbbbc9b81 LibWeb: Raise the baseline of text with veritcal-align: super
This raises the baseline of the given text by one third of the parent's
font size.
2025-03-27 23:30:57 +00:00
Aliaksandr Kalenik
fc45121b70 LibWeb: Size box as normal if it has aspect ratio but auto sizes
Otherwise we apply `calculate_stretch_fit_width()` instead of
calculating width based on the content inside the box, like other
browsers do.
2025-03-27 23:13:57 +00:00
Jelle Raaijmakers
006f276cab LibWeb: Copy IDBDatabase object stores through Vector(ReadonlySpan)
Prevents a crash because `ReadonlySpan.copy_to()` was trying to copy to
an empty vector.

Fixes #4127.
2025-03-27 23:13:32 +00:00
Andreas Kling
f5dd776b11 LibJS: Remove some irrelevant hash lookups in ESFO constructor
If we don't have parameter expressions, we don't need to collect
metadata about whether instantiated var names collide with parameter
names or function names, as these flags are only used in the parameter
code path.
2025-03-27 23:12:04 +00:00
Andreas Kling
c037bda455 LibJS: Use a premade shape for normal function objects
This avoids going through all the shape transitions when setting up the
most common form of ESFO.

This is extremely hot on Uber Eats, and this provides some relief.
2025-03-27 23:12:04 +00:00
Oliver Medhurst
60fd406903 LibWeb: Fix inside list style overriding content offset
Previously, if a horizontal margin was set on a list-item and
it was list-style-position: inside, it would effectively remove
that margin.
2025-03-27 23:10:09 +00:00
Oliver Medhurst
b272bb3373 LibWeb: Fix ::marker placement in tree
Fixes ::marker (pseudo-element) placement in the tree for list-items.

Previously:
- ::before
- content
- ::marker
- ::after

Now (matches Firefox, afaik per-spec):
- ::marker
- ::before
- content
- ::after
2025-03-27 23:10:09 +00:00
Manuel Zahariev
bc8f8676cc LibWebView: Additional unit tests for sanitized_url
Covers:
- single word search
- public domain suffixes, registered TLDs
- localhost
- url including words or search for url and words
2025-03-27 18:30:08 -04:00
Manuel Zahariev
9e7436a096 LibWebView: Better integration of sanitize_url with search
With search enabled:
- For a single word that does not look like a url: search (a
reported bug).
- If no suffix or a suffix that is not recognized: search.

In general:
- Respect the user's choice if they specified a scheme.
- Respect localhost and registered TLDs.
- As before, add file:// to filesystem files that exist.
2025-03-27 18:30:08 -04:00
Andreas Kling
5ea45da15f LibJS: Store NewObject result directly in preferred dst if possible
This avoids a Mov after every object literal.
2025-03-27 19:50:13 +00:00
Andreas Kling
900f209b34 LibJS: Make Optional<Operand> use less space
Shrink these down from 12 bytes to 8 bytes, which helps make many
bytecode instructions smaller.
2025-03-27 19:50:13 +00:00
Andreas Kling
a29d820f87 LibJS: Make Optional<IdentifierTableIndex> use less space
We can use the index's invalid state to signal an empty optional.
This makes Optional<IdentifierTableIndex> 4 bytes instead of 8,
shrinking every bytecode instruction that uses these.
2025-03-27 19:50:13 +00:00
Andreas Kling
904beef6d2 LibJS: Put newly instantiated functions into locals more efficiently
- Don't allocate a separate register, store directly into the local.
- Mark the local as initialized to avoid emitting TDZ checks.
2025-03-27 19:50:13 +00:00
Andreas Kling
6c70dc5f09 LibJS: Create FunctionParameters earlier in the parser
This avoids making multiple copies of the Vector<FunctionParameter> in
the parser.
2025-03-27 19:50:13 +00:00
Tim Ledbetter
d67a95c37e Tests: Remove print statement from crash test
Print statements aren't necessary in crash tests and will cause a
Javascript error when used.
2025-03-27 19:30:41 +00:00
Luke Wilde
42bc83a9d0 LibWebView+WebWorker: Attach an image decoder to worker instances
The createImageBitmap API can programmatically decode arbitrary images
from JS, and it's exposed in Workers, so they need an ImageDecoder
instance.
2025-03-27 17:47:27 +00:00
Jelle Raaijmakers
15103d172c LibWeb: Apply remaining vertical float clearance to next block level box
Whenever we generate line boxes, we might end up with a residual
vertical float clearance by way of having a `<br>` with `clear: ..` set.
Set the Y offset of the next block level box to place by this vertical
clearance.

Relates to #4058.
2025-03-27 17:21:56 +00:00
Ali Mohammad Pur
a83145c751 AK: Don't assert things about active union members in StringBase
This involves yeeting the 'invalid' union member as it was not really
checked against properly anyway; now the 'invalid' state is simply
StringData*{nullptr}, which was assumed to not exist previously.

Note that this is still accessing inactive union members, but is
promising to the compiler that they're fine where they are (the provided
debug macro AK_STRINGBASE_VERIFY_LAUNDER_DEBUG makes the
would-be-UB-if-not-for-launder ops verify that the operation is correct)

Should fix the GCC build.
2025-03-27 15:58:57 +00:00
Ali Mohammad Pur
c39eddaef8 Revert "AK: Don't try to free(UINTPTR_MAX) in StringData::delete()"
This reverts commit 693fe76d1c.
2025-03-27 15:58:57 +00:00
stelar7
209d05fcb4 LibWeb/IDB: Implement IDBDatabase::deleteObjectStore 2025-03-27 15:47:16 +00:00
stelar7
b11276e5c4 LibWeb/IDB: Implement IDBDatabase::objectStoreNames 2025-03-27 15:47:16 +00:00
stelar7
1ad9b3ee6e LibWeb/IDB: Implement create_a_sorted_name_list 2025-03-27 15:47:16 +00:00
stelar7
3879391fa6 LibWeb/IDB: Implement IDBObjectStore::name 2025-03-27 15:47:16 +00:00
stelar7
2e02b62126 LibWeb/IDB: Implement IDBObjectStore::autoIncrement 2025-03-27 15:47:16 +00:00
stelar7
b0453e044d LibWeb/IDB: Implement IDBObjectStore::transaction 2025-03-27 15:47:16 +00:00
stelar7
594ba28c35 LibWeb/IDB: Implement IDBObjectStore::keyPath 2025-03-27 15:47:16 +00:00
stelar7
1057c88fdd LibWeb/IDB: Implement IDBDatabase::createObjectStore 2025-03-27 15:47:16 +00:00
stelar7
3c5578cc87 LibWeb/IDB: Add internal ObjectStore type 2025-03-27 15:47:16 +00:00
stelar7
0979a154fd LibWeb/IDB: Implement is_valid_key_path 2025-03-27 15:47:16 +00:00
stelar7
c276c212a0 LibWeb/IDB: Implement KeyGenerator 2025-03-27 15:47:16 +00:00
Andreas Kling
8af5f25dd0 LibJS: Use a premade shape for normal function object prototypes
This avoids one shape allocation per function instantiation.
2025-03-27 15:00:43 +00:00
Andreas Kling
dba1798de7 LibJS: Make StringOrSymbol::as_string() return a const reference
No need to copy the FlyString here, we can avoid the ref count churn.
2025-03-27 15:00:43 +00:00
Andreas Kling
7477002e46 LibJS: Keep parsed function parameters in a shared data structure
Instead of making a copy of the Vector<FunctionParameter> from the AST
every time we instantiate an ECMAScriptFunctionObject, we now keep the
parameters in a ref-counted FunctionParameters object.

This reduces memory usage, and also allows us to cache the bytecode
executables for default parameter expressions without recompiling them
for every instantiation. :^)
2025-03-27 15:00:43 +00:00
Aliaksandr Kalenik
634f0c2469 LibWeb: Don't crash if ElementByIdMap already has an element
Let's simply reinsert the element respecting it's new position in the
DOM tree, instead of crashing.

Fixes regression in WPT tests caused by introducion of cache for
getElementById().
2025-03-27 14:44:51 +00:00
Timothy Flynn
9eca5febd1 LibDevTools+LibWebView+WebContent: Report exceptions to DevTools 2025-03-27 14:14:02 +00:00
Timothy Flynn
5d0fbc85e5 LibWebView+WebContent: Remove "styled" JS console IPC hooks
This was used by the built-in Inspector to send HTML-ified JS console
messages to the browser. It is no longer used.
2025-03-27 14:14:02 +00:00
Timothy Flynn
a5f3a60ed5 LibWeb: Report unhandled exceptions to the developer console
This was a spec bug which led to us reporting handled (rather than
unhandled) exceptions.

See: https://github.com/whatwg/html/commit/2d7f50a
2025-03-27 14:14:02 +00:00
Jelle Raaijmakers
683d6b77dd LibWeb: Apply vertical clearance to next line after <br> with clear:
We were introducing a line break and applying vertical clearance to the
inline formatting context, but that vertical clearance only applied to
new floating boxes. We should move the current block offset to the
vertical clearance to make sure the next line box starts beyond the
cleared floats.

There was a layout test for `<br>` with `clear: ..` set, but that test
did not actually do anything - removing the `clear` property would
result in the same layout. Replace that test with something that
actually tests float clearing.

Relates to #4058.
2025-03-27 13:57:59 +00:00
Lucien Fiorini
6b6e13e28c LibJS: Avoid emptying the return value register in try/finally
This works because at the end of the finally chunk, a
ContinuePendingUnwind is generated which copies the saved return value
register into the return value register. In cases where
ContinuePendingUnwind is not generated such as when there is a break
statement in the finally block, the fonction will return undefined which
is consistent with V8 and SpiderMonkey.
2025-03-27 12:18:30 +00:00
Sam Atkins
fbdabace8e CodeGenerators: Move some utilities out of GenerateCSSStyleProperties
These will be used by a similar generator for CSS at-rule descriptors.
For `get_snake_case_function_name_for_css_property_name()`, I've rolled
its behaviour into `snake_casify()` with an optional ability to trim
leading underscores.
2025-03-27 11:53:09 +00:00
Sam Atkins
2b67cb5f98 LibWeb/CSS: Move "serialize a CSS declaration" to Serialize.{h,cpp}
We need this in other places, so make it available for reuse. Also,
update step 4 which now only appends `value` if it contains
non-whitespace.
2025-03-27 11:53:09 +00:00
Sam Atkins
a2c89f585f LibWeb/CSS: Give all style values a visit_edges() method
Having this hidden away in ImageStyleValue meant that
CSSStyleProperties (and anyone else who holds style values) had to know
exactly which types need visiting. This is a footgun waiting to happen,
so make this a virtual method on CSSStyleValue instead.
2025-03-27 11:53:09 +00:00
Jelle Raaijmakers
c4bb74f40b LibWeb: Fix and improve float positioning behavior
Our recent change to get rid of the "move 1px at a time" algorithm in
the float positioning logic introduced the issue that potentially
intersecting float boxes were not evaluated in order anymore. This could
result in float boxes being pushed down further than strictly necessary.

By finding the highest point we can move the floating box to and
repeating the process until we're no longer intersecting any floating
box, we also solve some edge cases like intersecting with very long
floating boxes whose edges lay outside the current box' edges.

This is by no means the most efficient solution, but it is more correct
than what we had until now.

Fixes #4110.
2025-03-27 10:56:13 +00:00
SINF-KEN
32dbd6ab8f UI: Fix new error page 2025-03-27 08:34:38 +00:00
Jelle Raaijmakers
f340f8682b LibWeb: Do not clear float sides for floating boxes with clear: ..
We used to always clear the side data after encountering a box with
`clear: ..`, but this is not the right thing to do if that same box also
has `float: ..` set. For example, with `clear: right` and `float: left`
it might be that the next box still wants to clear the right side, and
since the previous box is floating it did not push the next box down far
enough to justify clearing the side data at that point.

This changes the logic to only clear the float side if the clearing box
itself is not floating. We also no longer clear the opposite side after
placing a floating box; that doesn't seem to be necessary anymore.

Fixes #4102.
2025-03-27 00:56:56 +00:00
Timothy Flynn
a6b664d4d0 Meta: Add -Wno-unqualified-std-cast-call to GCC compile flags
Otherwise we get a ton of errors about unqualified calls to `move` from
clangd.
2025-03-26 18:48:28 -04:00
Shannon Booth
f32cf33dee Tests/LibWeb: Import the main set of URLPattern WPT tests 2025-03-26 17:00:20 -04:00
Yaroslav Lelkin
b08903b39b Meta: Make shell_include.sh compatible with busybox
Busybox version of sort utility doesn't support --version-sort and
--check CLI args, only their short alternatives (-V and -c,
respectively).
Use the short alternatives to gain the busybox compatibility.
2025-03-26 20:59:01 +00:00
Aliaksandr Kalenik
e655b77393 LibWeb: Fix scroll offset application for SVG root box
Now we use `before_paint()` and `after_paint()` calls for SVG root box
to make sure that both clip and scroll are applied.

Fixes painting of SVG arrows on www.ubereats.com
2025-03-26 20:12:45 +00:00
SINF-KEN
1a34676046 UI: Style the crash page and update error page image
- Modified the error page
- changed the error/crash page

Co-authored-by: notnotnescap <97590612+nescapp@users.noreply.github.com>
2025-03-26 19:39:24 +00:00
Jelle Raaijmakers
002e79a658 LibWeb: Exclude trailing whitespace from line width when placing floats
When generating line boxes, we place floats simultaneously with the
other items on the same line. The CSS text spec requires us to trim the
whitespace at the end of each line, but we only did so after laying out
all the line boxes.

This changes the way we calculate the current line box width for floats
by subtracting the amount of pixels that the current trailing whitespace
is using.

Fixes #4050.
2025-03-26 19:35:38 +00:00
Sam Atkins
e8644d43db RequestServer: Remove useless Forward.h
The only class here that still exists is ConnectionFromClient... which
is the only class that includes Forward.h!
2025-03-26 18:22:50 +00:00
Aliaksandr Kalenik
7cae4fadbc LibWeb: Cache "has size containment" flag in Layout::Box
Allows us to avoid DOM node lookup whenever we need to query natural
size of a box during layout.

Makes 3-4% of `Box::preferred_aspect_ratio()` go away from profiles on
www.nyan.cat
2025-03-26 17:52:02 +00:00
Andreas Kling
693fe76d1c AK: Don't try to free(UINTPTR_MAX) in StringData::operator delete()
...in constant-evaluated contexts. This was messing up GCC when building
the test262 runner. UINTPTR_MAX is the StringBase "invalid" tag.
2025-03-26 10:47:55 -04:00
Aliaksandr Kalenik
85e28a29f0 LibWeb: Replace 1px iteration in y_for_float_to_be_inserted_here()
...with a loop through already inserted floating boxes that probes
potential insertion points on their edges.

Makes www.nyan.cat go faster.
2025-03-26 13:51:11 +00:00
Aliaksandr Kalenik
d8ff71fbb5 LibWeb: Delete parent state pointer in LayoutState
It's safe to remove this pointer because intrinsic layout should never
look up a box's state beyond its containing block.

This change affects the expectations of two layout tests, but both
already differ slightly from other browsers, and the difference between
expectations is less than 5px.
2025-03-26 12:08:09 +00:00
Andreas Kling
53cac71cec AK: Inline most StringBase member functions
More work on recovering the performance regression from
DeprecatedFlyString removal.

Local measurements on my MBP:
- 2.5% speedup on Octane/zlib.js
- 2% speedup on Octane/typescript.js
2025-03-26 12:04:00 +00:00
Jelle Raaijmakers
a0f3099333 CI: Make JS Benchmarks use the JS repl from the job with the same commit
In practice this does not make a big difference, but technically it
could happen that a second JS Repl artifact was built before the first
JS Benchmarks job is executed. So make sure to filter on commit ID.
2025-03-26 11:22:54 +00:00
sideshowbarker
a7cb2424af Tests: Skip the svg-inline-sizing/svg-inline.html for now
See https://github.com/LadybirdBrowser/ladybird/issues/3911. The
html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html WPT
test is causing a hang/timeout that prevents being able to run the test
suite to completion.
2025-03-26 10:19:27 +00:00
Sam Atkins
2d3dea0770 LibWeb/CSS: Update quirks-mode styling for form elements
The current HTML spec uses margin-block-end instead of margin-bottom.
2025-03-26 09:47:45 +00:00
Sam Atkins
b2873d7ed6 LibWeb/CSS: Add new list-style-position quirk
Corresponds to d79381d822

In quirks mode, a `<li>` with no parent list element now has
`list-style-position: inside`.
2025-03-26 09:47:45 +00:00
Sam Atkins
612aabaedf Tests: Import list-style quirks test from WPT 2025-03-26 09:47:45 +00:00
Aliaksandr Kalenik
8cae20af1b LibWeb: Maintain a mapping for fast lookup in getElementById()
With this change we maintain a data structure that maps ids to
corresponding elements. This allows us to avoid tree traversal in
getElementById() in all cases except ones when lookup happens for
unconnected elements.
2025-03-26 08:36:25 +00:00
Andreas Kling
7165d69868 AK: Inline more of the String and FlyString member functions
This is to help recover some of the performance regression from no
longer using DeprecatedFlyString (which was aggressively inlined.)
2025-03-26 02:20:11 +00:00
Aliaksandr Kalenik
275985ff3d LibWeb: Ignore non-box element while collecting abspos nodes for layout
All abspos boxes are expected to be blockified, so we are certain that
we can ignore non-box elements when collecting abspos nodes for layout.

Fixes a crash caused by an attempt to cast a BreakNode to a Box while
performing abspos layout.
2025-03-26 00:17:53 +00:00
Andreas Kling
d856858015 LibWeb: Cache and reuse inline style for text input shadow trees
Instead of reparsing the style attributes every time we instantiate
the internal shadow tree for a text input element, we now parse them
once (in the internal CSS realm) and reuse them for all elements.

Roughly a ~10% speedup on Speedometer 2.1 :^)
2025-03-25 23:57:00 +00:00
Andreas Kling
ba030f0363 LibWeb: Add an engine-internal CSS realm for internal style parsing
This is used for default UA style right now, and we'll expand its use in
the near future.

Note that this required teaching the CSS parser to handle url()
functions when there's no document URL to resolve them against. If we
don't handle that, namespace rules in UA style don't parse correctly.
2025-03-25 23:57:00 +00:00
Andreas Kling
c12f8b80dc LibJS: Add fast_is<T> helpers for all the primitive wrapper objects
The JS runtime is full of checks for is<NumberObject> and friends.
They were showing up in a Speedometer profile as ~1% spent in
dynamic_cast, and this basically chops that down to nothing.
2025-03-25 23:57:00 +00:00
Andreas Kling
3cc5b1a6a5 LibJS: Do a bit less stuff in PropertyKey::try_coerce_into_number()
The many out-of-line function calls here stood out in a profile.
2025-03-25 23:57:00 +00:00
Jelle Raaijmakers
91d6902725 UI: Add Cmd+U as a shortcut for "View Source" to AppKit
This mirrors the shortcut we have in our Qt UI.
2025-03-25 17:08:42 -04:00
Jelle Raaijmakers
a9ef5b4924 Meta: Increase max open file descriptors in WPT.sh
On some macs, the default maximum number of file descriptors is 256.
This quickly makes the WPT runner run out of descriptors, so let's check
the active value and increase the soft limit if necessary.
2025-03-25 16:24:06 -04:00
Jelle Raaijmakers
6a3c3ee291 LibWeb: Coerce NaNs to 0 when escaping top-level calculations 2025-03-25 19:53:36 +00:00
Jelle Raaijmakers
545d151948 LibWeb: Make transform: scale(calc(..)) work
The `transform` property supports transform functions that sometimes
need their `calc(percentage)` values to be converted to a number instead
of a length. Currently this only applies to the `scale*` family of
functions, which are marked as such in `TransformFunctions.json`.

We were not consistently applying the `NumberPercentage` type to these
functions though, and in addition, any `NumberPercentage` value would
not consider calculated values.
2025-03-25 19:53:36 +00:00
Andreas Kling
202cbe7df6 LibJS: Constant-fold unary expressions
!0 and !1 are very common patterns in minified JavaScript, and we should
figure out that they're constants. :^)
2025-03-25 19:14:12 +00:00
Luke Wilde
de892abdba LibWeb: Don't apply DPR or zoom level to screen.{width,height}
Safari and WebKit don't apply these, while Firefox only applies the
zoom level. This fixes https://x.com/ showing the tablet view.
2025-03-25 17:34:41 +00:00
Psychpsyo (Cameron)
c7926b2212 LibWeb: Change while to for loop 2025-03-25 15:50:45 +00:00
stelar7
1844e10cd3 LibWeb/IDB: Correctly check if transaction was aborted
The associated databases upgrade transaction could be
null at the time we try to access it here.
2025-03-25 10:50:03 +00:00
stelar7
e8b7447c36 LibWeb/IDB: Abort transaction in database upgrade if needed 2025-03-25 10:50:03 +00:00
stelar7
923927564d LibWeb/IDB: Set the source of a IDBRequest 2025-03-25 10:50:03 +00:00
Aliaksandr Kalenik
090ac66af1 LibWeb: Repeat grid track sizing with minmax where both are not definite
...should be treated as invalid value.
2025-03-25 09:53:04 +00:00
Sam Atkins
88e11eea2d LibWeb: Implement functional pseudo-element parsing
"Functional" as in "it's a function token" and not "it works", because
the behaviour for these is unimplemented. :^)

This is modeled after the pseudo-class parsing, but with some changes
based on things I don't like about that implementation. I've
implemented the `<pt-name-selector>` parameter used by view-transitions
for now, but nothing else.
2025-03-25 07:54:13 +00:00
Sam Atkins
5cf04a33ad LibWeb/CSS: Add method for parsing <custom-ident> directly
We specifically want to parse one inside a selector, where we only care
about the string itself and don't want a whole style value.
2025-03-25 07:54:13 +00:00
Sam Atkins
285fbc8f1c LibWeb/CSS: Parse local() font sources more correctly
There were several issues with the previous parsing code, like ignoring
trailing tokens, not handling whitespace, and not requiring the value
to be a `<family-name>`. So, fix all that.

Also correct the serialization code, which didn't call
`serialize_a_string()` previously.
2025-03-25 07:53:59 +00:00
Sam Atkins
93a2c9946f LibWeb: Use FlyString for local font sources
The next commit will make it so we always have a FlyString, so this lets
us keep using it instead of turning it into a String.
2025-03-25 07:53:59 +00:00
Sam Atkins
f8536fc48a LibWeb/CSS: Split out <family-name> parsing
This type is used individually elsewhere in the spec. This also lets us
separate out the `<generic-family>` type.
2025-03-25 07:53:59 +00:00
Timothy Flynn
2e5e5d3816 LibWeb: Pass along the init dictionary for error / buffer change events
Otherwise, information stored in the base event init dictionary will be
dropped.
2025-03-25 07:52:12 +00:00
Tim Ledbetter
9ce5bbe059 LibWeb: Remove CubicBezier cached sample inline cache
This reduces the size of CubicBezier objects from 1592 bytes to 56
bytes.
2025-03-25 07:51:27 +00:00
Jess
f3a937ee76 LibJS: Fix integer overflow in target_offset of TypedArray.set() 2025-03-25 07:45:42 +00:00
Andreas Kling
dc83f3375c LibWeb: Don't drop entire layout tree on object element update
It's sufficient to just rebuild the layout subtree rooted at the object
element itself.
2025-03-25 07:31:42 +00:00
Andreas Kling
a6836054cc LibWeb: Don't drop entire layout tree on input element src change 2025-03-25 07:31:42 +00:00
Andreas Kling
305a5ad30b LibWeb: Don't drop entire layout tree for SVG element transform changes
A partial update is enough here and avoids a lot of work.

Dramatically reduces time spent on relayouts on https://duolingo.com/
2025-03-25 07:31:42 +00:00
Andreas Kling
dc56435ecd LibWeb: Skip "overlay" paint phase when there's no inspected node
This avoids a bunch of tree traversal that doesn't find anything to
paint anyway.
2025-03-25 07:31:42 +00:00
Andreas Kling
62d450c632 LibWeb: Fix layout invalidation debug logging (UPDATE_LAYOUT_DEBUG)
This was broken in a recent refactoring and no longer printed for
anything but document invalidations.
2025-03-25 07:31:42 +00:00
Aliaksandr Kalenik
6b9e8cf40c LibWeb: Lazily allocate data required to run CSS animations
Instead of reserving space for data required to run animations in every
DOM element, we now allocate it lazily only if element actually has some
animations. This allows us to save 336 bytes on non-animated DOM
elements.
2025-03-25 00:15:36 +01:00
Andreas Kling
6b6d3b32a4 LibRegex: Remove the StringCopyMatches mode
This mode made a lot of incorrect assumptions about string lifetimes,
and instead of fixing it, let's just remove it and tweak the few unit
tests that used it.
2025-03-24 22:27:17 +00:00
Andreas Kling
f1914893e9 LibJS+LibWeb: Remove more uses of DeprecatedFlyString 2025-03-24 22:27:17 +00:00
Andreas Kling
46a5710238 LibJS: Use FlyString in PropertyKey instead of DeprecatedFlyString
This required dealing with *substantial* fallout.
2025-03-24 22:27:17 +00:00
Andreas Kling
fc744e3f3f LibJS: Add fast path for strings in Value::to_property_key()
If the Value is already a primitive string, we can skip all the
conversion ceremony and return a PropertyKey right away.
2025-03-24 22:27:17 +00:00
Andreas Kling
1662223e89 AK: Tweak ShortString bit layout slightly
Move the byte count one step to the left in order to make space
for the JS::StringOrSymbol flag.
2025-03-24 22:27:17 +00:00
Andreas Kling
53da8893ac LibJS: Replace PropertyKey(char[]) with PropertyKey(FlyString)
...and deal with the fallout.
2025-03-24 22:27:17 +00:00
Andreas Kling
d7908dbff5 LibJS: Change PropertyKey(ByteString) to PropertyKey(String)
...and deal with the fallout.
2025-03-24 22:27:17 +00:00
Andreas Kling
3b5032c4b1 LibJS: Remove unused StringOrSymbol constructors 2025-03-24 22:27:17 +00:00
Andreas Kling
e83a2c2369 LibJS: Prefer Value::to_string() over to_byte_string() in more places
We should always prefer working with String, and Value::to_string() may
even return a cached String if the Value refers to a primitive string,
but no caching occurs for ByteString.
2025-03-24 22:27:17 +00:00
Timothy Flynn
8155377b5f LibWebView: Move stored settings to the system configuration directory 2025-03-24 22:55:35 +01:00
Aliaksandr Kalenik
a8285f255b LibJS: Skip allocation of temp object for primitive types in Value::get
Previously, `String.prototype.split()` caused the construction of a
temporary StringObject when a string primitive was passed as an
argument, solely to perform a Symbol.split lookup. This change allows
skipping that allocation by looking directly into the prototype of
primitive values.

As a result, we can avoid ~200000 StringObject allocations in a single
test from the Speedometer 2 benchmark.

Co-Authored-By: Andreas Kling <andreas@ladybird.org>
2025-03-24 20:38:11 +01:00
Aliaksandr Kalenik
057e643a63 LibWeb: Don't assume length-percentage is always a length [GFC]
Fixes crashing when trying to get length from LengthPercentage with
percentage value.
2025-03-24 18:59:21 +01:00
Jelle Raaijmakers
685cc1aae8 Everywhere: Remove Nix build support
A significant portion of reported build problems come from people trying
to build Ladybird with Nix, and it seems there's always something broken
for someone. The maintainers are currently not focused on supporting
Nix, and as a result PRs are not reviewed as well as they could have
been.

This removes all Nix-related files.
2025-03-24 17:22:08 +00:00
Jelle Raaijmakers
582084e74e CI: Call webhook as soon as new JS benchmark results are in 2025-03-24 12:49:30 +01:00
Sam Atkins
82b1d5537e Documentation: Document the new PseudoElements.json file 2025-03-24 09:49:50 +00:00
Sam Atkins
9e65291ebd LibWeb/CSS: Discard unsupported style properties on pseudo-elements
Quite simply, ignore any declarations for properties we don't want,
while computing a pseudo-element's style.

I've imported a WPT test for this, which fails without this patch.
2025-03-24 09:49:50 +00:00
Sam Atkins
1108988656 LibWeb/CSS: Generate property-filtering code for pseudo-elements
Pseudo-elements have specific rules about which CSS properties can be
applied to them. This is a first step to supporting that.

- If a property whitelist isn't present, all properties are allowed.
- Properties are named as in CSS.
- Names of property groups are prefixed with `#`, which makes this match
  the spec more clearly. These groups are implemented directly in the
  code generator for now.
- Any property name beginning with "FIXME:" is ignored, so we can mark
  properties we don't implement yet.
2025-03-24 09:49:50 +00:00
Sam Atkins
193adee164 LibWeb/CSS: Implement aliases for pseudo-elements
We previously supported a few -webkit vendor-prefixed pseudo-elements.
This patch adds those back, along with -moz equivalents, by aliasing
them to standard ones. They behave identically, except for serializing
with their original name, just like for unrecognized -webkit
pseudo-elements.

It's likely to be a while before the forms spec settles and authors
start using the new pseudo-elements, so until then, we can still make
use of styles they've written for the non-standard ones.
2025-03-24 09:49:50 +00:00
Sam Atkins
2c86fd539d LibWeb: Generate an enum for generated pseudo-elements 2025-03-24 09:49:50 +00:00
Sam Atkins
021e3f5c7d LibWeb/CSS: Generate is_has_allowed_pseudo_element() 2025-03-24 09:49:50 +00:00
Sam Atkins
ffa1dba96a LibWeb: Generate pseudo-element code from JSON
Initially, this generates the enum and to/from-string functions. The
JSON itself contains more data than that, but it's unused for now.
2025-03-24 09:49:50 +00:00
Sam Atkins
0ed2e71801 LibWeb/CSS: Move and rename PseudoElement types to prep for code gen
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.

In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
2025-03-24 09:49:50 +00:00
Jelle Raaijmakers
b11064c0ae CI: Reduce js-benchmarks artifact retention to 90 days
This is GitHub's default maximum. Prevents generating a warning on each
workflow run.
2025-03-24 01:20:00 +01:00
Manuel Zahariev
4ed8e9e596 LibCrypto: Improve precision of Crypto::BigFraction::to_double()
Before:
    - FIXME: very naive implementation
    - was preventing passing some Temporal tests
    - https://github.com/tc39/test262
    - https://github.com/LadybirdBrowser/libjs-test262

Bonus: Unrelated formatting change (Line 249) that unblocks the CI
lint check.
2025-03-23 19:33:25 +01:00
Manuel Zahariev
d2ea77c099 LibCrypto: Improve efficiency of UnsignedBigInteger::shift_left
Before:
- a separate Word element allocation of the underlying Vector<Word> was
necessary for every new word in a multi-word shift
- two additional temporary UnsignedBigInteger buffers were allocated
and passed through, including in downstream calls (e.g. Multiplication)
- an additional allocation and word shift for the carry
- FIXME note seems to point to some of these issues

After:
- main change is in LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp
- one single allocation per call, using shift_left_by_n_words
- only the input "number" and "output" need to be allocated by the
  caller
- downstream calls are adapted not to allocate or pass temporary
  buffers
- noticeable performance improvement when running TestBigInteger:
  0.41-0.42s (before) to 0.28-0.29s (after) Intel Core i9 laptop

Bonus: remove unused variables from UnsignedBigInteger::divided_by
- These were likely cut-and-paste artifacts from
  UnsignedBigInteger::multiplied_by; not caught by "unused-varible".

NOTE: making this change in a separate commit than shift_right, even if
it touches the same file BitwiseOperations.cpp since:
- it is a "bonus" addition: not necessary for fixing the shift_right
  bug, but logically unrelated to the shift_right code
- it brings a chain of downstream interface modifications (7 files),
  unrelated to shift_right
2025-03-23 19:33:25 +01:00
Manuel Zahariev
05cfbdd6fb LibCrypto: Add support for shift_right more than one word
- Before: UnsignedBigInteger::shift_right( n ) trigger index
  verification error for n>31. An assumption of
  num_bits<UnsignedBigInteger::BITS_IN_WORD was being made
- After: shift_right( n ) works correctly for n>31.

NOTE: "bonus" change; not necessary for fixing BigFraction::to_double
2025-03-23 19:33:25 +01:00
Noah
add380d6e2 LibWeb: Update Element::directionality() for bdi elements to match spec
This fixes three WPT test cases at html/dom/elements/global-attributes/dir-assorted.window.html

Update test expectations for Tests/LibWeb/Text/expected/wpt-import/css/selectors/dir-pseudo-on-bdi-element.txt
2025-03-23 09:58:42 +01:00
Andreas Kling
5f12b2a05d LibJS: Make IteratorRecord inherit from Cell, not Object
This shaves its size down from 104 bytes to 48 bytes, cutting GC
pressure caused by this type in more than half.
2025-03-22 16:59:44 -05:00
Andreas Kling
1d88c4529c LibJS: Allow JS::Value to store a non-object Cell
This will allow us to refer to non-object Cells more readily in bytecode
and opens up for some nice optimizations.
2025-03-22 16:59:44 -05:00
Andreas Kling
f0abf5a43b LibWeb: Avoid allocating DOMRect objects for internal engine use
Instead of bothering the GC heap with a bunch of DOMRect allocations,
we can just pass around CSSPixelRect internally in many cases.

Before this change, we were generating so much DOMRect garbage that
we had to do a garbage collection *every frame* on the Immich demo.
This was due to the large number of intersection observers checked.

We still need to relax way more when idle, but for comparison, before
this change, when doing nothing for 10 seconds on Immich, we'd spend
2.5 seconds updating intersection observers. After this change, we now
spend 600 ms.
2025-03-22 14:33:59 -05:00
Jelle Raaijmakers
bf517f9ac2 LibGfx+LibWeb: Convert bitmap alpha type when creating ImmutableBitmaps
When decoding data into bitmaps, we end up with different alpha types
(premultiplied vs. unpremultiplied color data). Unfortunately, Skia only
seems to handle premultiplied color data well when scaling bitmaps with
an alpha channel. This might be due to Skia historically only supporting
premultiplied color blending, with unpremultiplied support having been
added more recently.

When using Skia to blend bitmaps, we need the color data to be
premultiplied. ImmutableBitmap gains a new method to enforce the alpha
type to be used, which is now used by SharedResourceRequest and
CanvasRenderingContext2D to enforce the right alpha type.

Our LibWeb tests actually had a couple of screenshot tests that exposed
the graphical glitches caused by Skia; see the big smiley faces in the
CSS backgrounds tests for example. The failing tests are now updated to
accommodate the new behavior.

Chromium and Firefox both seem to apply the same behavior; e.g. they
actively decode PNGs (which are unpremultiplied in nature) to a
premultiplied bitmap.

Fixes #3691.
2025-03-22 17:49:38 +01:00
Jelle Raaijmakers
c6644c92e7 LibGfx: Factor out PNG frame decoding logic
The logic for decoding APNGs and single-frame PNGs had some duplicated
code. No functional changes.
2025-03-22 17:49:38 +01:00
Jelle Raaijmakers
d30c217866 LibWeb: Change ASSERTs into VERIFYs when comparing bitmap alpha types
For non-debug builds, this is still very useful to check and doesn't
significantly impact any hot paths.
2025-03-22 17:49:38 +01:00
Jelle Raaijmakers
e4a5be0206 LibGfx+ImageDecoder: Use RefPtr<Bitmap> instead of optional
Simplify the list of bitmaps a bit by changing
`Optional<NonnullRefPtr<Bitmap>>` into `RefPtr<Bitmap>`. No functional
changes.
2025-03-22 17:49:38 +01:00
aplefull
19bee8393d LibGfx: Add support for YCCK jpeg files 2025-03-22 17:35:29 +01:00
Tim Ledbetter
7b0b6e7493 LibWeb/CSS: Make empty GridTrackSize value serialize to "none"
This is the default value of the `grid-template-rows` and
`grid-template-columns` properties.
2025-03-22 17:33:37 +01:00
Timothy Flynn
9bdd22c6b1 UI/Qt: Add a menu item to open about:settings
This replaces the existing menu item that would open the Qt settings
dialog. That menu item still exists, but is no longer the default
settings action.
2025-03-22 17:27:45 +01:00
Timothy Flynn
7a5387b0ab UI/AppKit: Add a menu item to open about:settings 2025-03-22 17:27:45 +01:00
Timothy Flynn
b169a98495 LibWeb+LibWebView+WebContent: Introduce a basic about:settings page
This adds a basic settings page to manage persistent Ladybird settings.
As a first pass, this exposes settings for the new tab page URL and the
default search engine.

The way the search engine option works is that once search is enabled,
the user must choose their default search engine; we do not apply any
default automatically. Search remains disabled until this is done.

There are a couple of improvements that we should make here:

* Settings changes are not broadcasted to all open about:settings pages.
  So if two instances are open, and the user changes the search engine
  in one instance, the other instance will have a stale UI.

* Adding an IPC per setting is going to get annoying. It would be nice
  if we can come up with a smaller set of IPCs to send only the relevant
  changed settings.
2025-03-22 17:27:45 +01:00
Timothy Flynn
e084a86861 LibWebView+UI: Introduce a persistent settings object
This adds a WebView::Settings class to own persistent browser settings.
In this first pass, it now owns the new tab page URL and search engine
settings.

For simplicitly, we currently use a JSON format for these settings. They
are stored alongside the cookie database. As of this commit, the saved
JSON will have the form:

    {
        "newTabPageURL": "about:blank",
        "searchEngine": {
            "name": "Google"
        }
    }

(The search engine is an object to allow room for a future patch to
implement custom search engine URLs.)

For Qt, this replaces the management of these particular settings in the
Qt settings UI. We will have an internal browser page to control these
settings instead. In the future, we will want to port all settings to
this new class. We will also want to allow UI-specific settings (such as
whether the hamburger menu is displayed in Qt).
2025-03-22 17:27:45 +01:00
Timothy Flynn
b4fde1ef64 LibWebView: Remove non-generic search engines
It really doesn't make sense for GitHub to be the default search engine.
If some really wants this, we can eventually implement setting custom
search engine URLs.
2025-03-22 17:27:45 +01:00
Timothy Flynn
a69ecc3943 UI: Add a default CSS file for internal Ladybird pages
In order to maintain a consistent look and feel between internal about:
pages going forward, let's use a central CSS file to define Ladybird
colors and some common form control styles.
2025-03-22 17:27:45 +01:00
Timothy Flynn
5f0f97b3cc LibWeb: Do not insert "return" key presses into input element values
When the return key is pressed, we try to handle it as a commit action
for input elements. However, we would then go on to actually insert the
return key's code point (U+000D) into the input element. This would be
sanitized out, but would leave the input element in a state where it
thinks it has text to commit. This would result in a change event being
fired when the return key is pressed multiple times in a row.

We were also firing the beforeinput/input events twice for all return
key presses.

To fix this, this patch changes the input event target to signify if it
actually handled the return key. If not (i.e. for textarea elements),
only then do we insert the code point. We also must not fall through to
the generic key handler, to avoid the repeated input events.
2025-03-22 17:27:45 +01:00
Timothy Flynn
206ec6694c LibWeb: Update the select element's text when setting the selected index
We were updating the IDL values, but the rendered text would remain on
the previously selected value.
2025-03-22 17:27:45 +01:00
Timothy Flynn
9b6ae962d0 LibWebView+UI: Handle DPR for select elements like other menus
The select dropdown was doing its own ad-hoc method of handling DPR. We
now handle it just like other context menus. Previously, the drop down
in the AppKit chrome was twice as large as it should be.
2025-03-22 17:27:45 +01:00
Timothy Flynn
3961a4f16a AK: Fully qualify use of move in TemporaryChange
For some reason, after some seemingly unrelated upcoming changes, the
unqualified `move`s in this header result in an ADL failure:

AK/TemporaryChange.h:22:39: error: call to function 'move' that is
neither visible in the template definition nor found by argument-
dependent lookup
   22 |     ~TemporaryChange() { m_variable = move(m_old_value); }
      |                                       ^

Libraries/LibDNS/Resolver.h:491:29: note: in instantiation of member
function 'AK::TemporaryChange<bool>::~TemporaryChange' requested here
  491 |             TemporaryChange change(m_attempting_restart, true);
2025-03-22 17:27:45 +01:00
Tim Ledbetter
cbf47abd24 LibWeb/CSS: Set the initial value of the appearance property to "none" 2025-03-22 17:05:17 +01:00
Tim Ledbetter
ecd6636b3e LibWeb/CSS: Use "0s" as the initial value for animation-duration 2025-03-22 17:04:33 +01:00
Tim Ledbetter
e1f6a170d5 LibWeb: Invalidate style when media content attribute changes
Previously, we would only invalidate style when setting the `media` IDL
attribute; changing the attribute via `setAttribute()` and
`removeAttribute()` had no immediate effect.
2025-03-22 17:03:56 +01:00
Ryan Liptak
0b0f47e320 LibWeb: Make named character references more spec-compliant & efficient
There are two changes happening here: a correctness fix, and an
optimization. In theory they are unrelated, but the optimization
actually paves the way for the correctness fix.

Before this commit, the HTML tokenizer would attempt to look for named
character references by checking from after the `&` until the end of
m_decoded_input, which meant that it was unable to recognize things like
named character references that are inserted via `document.write` one
byte at a time. For example, if `&notin;` was written one-byte-at-a-time
with `document.write`, then the tokenizer would only check against `n`
since that's all that would exist at the time of the check and therefore
erroneously conclude that it was an invalid named character reference.

This commit modifies the approach taken for named character reference
matching by using a trie-like structure (specifically, a deterministic
acyclic finite state automaton or DAFSA), which allows for efficiently
matching one-character-at-a-time and therefore it is able to pick up
matching where it left off after each code point is consumed.

Note: Because it's possible for a partial match to not actually develop
into a full match (e.g. `&notindo` which could lead to `&notindot;`),
some backtracking is performed after-the-fact in order to only consume
the code points within the longest match found (e.g. `&notindo` would
backtrack back to `&not`).

With this new approach, `document.write` being called one-byte-at-a-time
is handled correctly, which allows for passing more WPT tests, with the
most directly relevant tests being
`/html/syntax/parsing/html5lib_entities01.html`
and
`/html/syntax/parsing/html5lib_entities02.html`
when run with `?run_type=write_single`. Additionally, the implementation
now better conforms to the language of the spec (and resolves a FIXME)
because exactly the matched characters are consumed and nothing more, so
SWITCH_TO is able to be used as the spec says instead of RECONSUME_IN.

The new approach is also an optimization:

- Instead of a linear search using `starts_with`, the usage of a DAFSA
  means that it is always aware of which characters can lead to a match
  at any given point, and will bail out whenever a match is no longer
  possible.
- The DAFSA is able to take advantage of the note in the section
  `13.5 Named character references` that says "This list is static and
  will not be expanded or changed in the future." and tailor its Node
  struct accordingly to tightly pack each node's data into 32-bits.
  Together with the inherent DAFSA property of redundant node
  deduplication, the amount of data stored for named character reference
  matching is minimized.

In my testing:

- A benchmark tokenizing an arbitrary set of HTML test files was about
  1.23x faster (2070ms to 1682ms).
- A benchmark tokenizing a file with tens of thousands of named
  character references mixed in with truncated named character
  references and arbitrary ASCII characters/ampersands runs about 8x
  faster (758ms to 93ms).
- The size of `liblagom-web.so` was reduced by 94.96KiB.

Some technical details:

A DAFSA (deterministic acyclic finite state automaton) is essentially a
trie flattened into an array, but it also uses techniques to minimize
redundant nodes. This provides fast lookups while minimizing the
required data size, but normally does not allow for associating data
related to each word. However, by adding a count of the number of
possible words from each node, it becomes possible to also use it to
achieve minimal perfect hashing for the set of words (which allows going
from word -> unique index as well as unique index -> word). This allows
us to store a second array of data so that the DAFSA can be used as a
lookup for e.g. the associated code points.

For the Swift implementation, the new NamedCharacterReferenceMatcher
was used to satisfy the previous API and the tokenizer was left alone
otherwise. In the future, the Swift implementation should be updated to
use the same implementation for its NamedCharacterReference state as
the updated C++ implementation.
2025-03-22 16:03:44 +01:00
Jelle Raaijmakers
2752e01fe7 CI: Add js-benchmarks workflow
This workflow starts after a successful js-artifacts workflow, picks up
the JS repl binary and runs our js-benchmarks tool. It does not yet
publish or otherwise store the benchmark results, but it's a start!
2025-03-22 13:05:43 +01:00
Jelle Raaijmakers
8671b0568d CI: Rename ladybird-js-artifacts to js-artifacts
Everything is Ladybird in this repository :^)
2025-03-22 13:05:43 +01:00
Aliaksandr Kalenik
c49dd2036b LibWeb: Mark height as definite before doing inner layout of abspos
...boxes with non-auto height.

We know for sure that by the time we layout abspos boxes, their
containing block has definite height, so it's possible to resolve
non-auto heights and mark it as definite before doing inner layout.

Big step towards having reasonable performance on
https://demo.immich.app/photos because now we avoid a bunch of work
initiated by mistakenly invoked intersection observer callbacks.

Co-Authored-By: Andreas Kling <andreas@ladybird.org>
2025-03-21 14:46:31 -05:00
Tim Ledbetter
ed62aa6224 Revert "LibJS: Reduce number of proxy traps called during for..in…
…iteration"

This reverts commit 357eeba49c.
2025-03-21 11:44:21 -05:00
Aliaksandr Kalenik
9ec986753a LibWeb: Delete const from GridDimension function parameters in GFC
Using const on primitive type was only adding unnecessary noise.
2025-03-21 15:19:39 +01:00
Aliaksandr Kalenik
76482559d0 LibWeb: Unify grid item's width and height resolution in GFC
It was annoying to maintain two separate but almost identical functions
that gradually accumulated small differences over time. This change
replaces them with a single function that resolves either width or
height, depending on the specified dimension.
2025-03-21 15:19:39 +01:00
Aliaksandr Kalenik
484cd8a0c3 LibWeb: Move item's available space getter into GridItem method in GFC
No behavior change intended.
2025-03-21 15:19:39 +01:00
Aliaksandr Kalenik
2ce40b5687 LibWeb: Move preferred size getter into GridItem method in GFC
No behavior change intended.
2025-03-21 15:19:39 +01:00
Aliaksandr Kalenik
c40f88ddcb LibWeb: Move minimum/maximum size getter into GridItem method in GFC
No behavior change intended.
2025-03-21 15:19:39 +01:00
Tim Ledbetter
40760308c6 LibWeb: Don't crash when border-spacing is set to a calc() value
Previously, the browser would crash if the `border-spacing` property
had 2 lengths and either one of these was set to a `calc()` value.
2025-03-21 08:16:30 +00:00
Andreas Kling
c528c01745 LibJS: Elide empty variable environment for default parameters
No need to create a separate variable environment if all the parameters
are going into locals anyway.
2025-03-21 00:58:34 +01:00
Andreas Kling
b971e1ece0 LibJS: Mark locals as outside TDZ immediately after initializing
This avoids emitting TDZ checks for multiple bindings declared and
referenced within one variable declaration, i.e:

    var foo = 0, bar = foo;

In the above case, we'd emit an unnecessary TDZ check for the second
reference to `foo`.
2025-03-21 00:58:34 +01:00
Jelle Raaijmakers
01031bcccb Revert "CI: Only run builds after successful linting"
This reverts commits bf333eaea2 and
6f69a445bd.

The commit linter needs to run on event `pull_request_target` to have
access to its secret token, which means we cannot have a dependency on
that job from another workflow that is run as a result of the
`pull_request` event.

Additionally, the linters were no longer run for first-time
contributors. This isn't a huge problem but it was nice that a
preliminary check took place before running the full CI on their PRs.
2025-03-21 00:02:44 +01:00
Andreas Kling
357eeba49c LibJS: Reduce number of proxy traps called during for..in iteration
Before this change, we would enumerate all the keys with
[[OwnPropertyKeys]], and then do [[GetOwnPropertyDescriptor]] twice for
each key as we went through them.

We now only do one [[GetOwnPropertyDescriptor]] per key, which
drastically reduces the number of proxy traps when those are involved.
The new trap sequence matches what you get with V8, so I don't think
anyone will be unpleasantly surprised here.
2025-03-20 17:50:02 -05:00
Jelle Raaijmakers
acc9499c5d UI: Show "Disable" title in DevTools disable button
The "disable DevTools" button looked like a "close this notification"
button to me, and although a tooltip was set, it only showed up
immediately on the AppKit UI and not the Qt version.

This makes the behavior of clicking the disable button a lot clearer by
showing a button with "Disable" as its title.
2025-03-20 17:44:07 -04:00
Andreas Kling
49d2a8df23 LibJS: Elide empty lexical environments for parameter evaluation
If all the parameter default values end up in locals, the lexical
environment we create to hold them would never be used for anything,
and so we can elide it and avoid the GC work.
2025-03-20 12:51:21 -05:00
Andreas Kling
842a189c2e LibJS: Elide empty lexical environment when direct eval() is present
Direct eval() always creates a new lexical environment, so we don't have
to worry about those here. The var environments still need special care.
2025-03-20 12:51:21 -05:00
Andreas Kling
f6141df589 LibJS: Remove unnecessary check in for..in iterator implementation 2025-03-20 12:51:21 -05:00
Andreas Kling
fb3d1c2754 LibJS: Reuse the internal iterator object across a for..in iteration
Instead of creating a new iterator result Object for every step of
for..in iteration, we can create a single object up front and reuse it
for every step. This avoids generating a bunch of garbage that isn't
observable by author code anyway.

We can also reuse the existing premade shape for these objects.
2025-03-20 12:51:21 -05:00
Andreas Kling
37bf083536 LibJS: Do a single pass to prune non-enumerable keys for iteration
Instead of pruning as-we-go, which means a ton of hash lookups,
we now only do a single pass to prune all non-enumerable keys when
setting up for for..in iteration.
2025-03-20 12:51:21 -05:00
Andreas Kling
660d533b50 LibJS: Don't assume [[GetOwnPropertyDescriptor]] always succeeds
It can fail if we're talking to a badly-behaved proxy when enumerating
object properties for iteration.
2025-03-20 12:51:21 -05:00
Andreas Kling
37c7eb14fe LibJS: Let GetGlobal cache module environment lookups when possible 2025-03-20 12:51:21 -05:00
Andreas Kling
8fcff2fa18 LibJS: Store Module::environment() as ModuleEnvironment
Let's use a more specific type here to allow for devirtualization.
2025-03-20 12:51:21 -05:00
Andrew Kaster
603df37a88 LibWeb: Devirtualize CSS::CalculatedOr
This fixes a compile warning on GCC 13.3.0 where it warns about the
use of Variant within this class with no key function. Since the class
was almost a CRTP base class, make it a real one.
2025-03-20 11:36:09 -06:00
Andrew Kaster
f22f6e1f5b CMake: Remove unused CMake functions 2025-03-20 11:36:09 -06:00
Tim Ledbetter
5bfbb7abe6 LibWeb: Preserve unit when serializing angle values
Previously, when serializing an angle value, we would always convert it
to degrees. We now canonicalize the angle value only when serializing
its computed value.
2025-03-20 16:59:27 +00:00
Tim Ledbetter
d0be5a0cdf LibWeb: Preserve unit when serializing time values
Previously, when serializing a time value, we would always convert it
to seconds. We now canonicalize the time value only when serializing
its computed value.
2025-03-20 16:59:27 +00:00
Tim Ledbetter
2672fe99b7 LibWeb: Set correct longhands if grid-area subproperties are omitted 2025-03-20 16:59:27 +00:00
Tim Ledbetter
c029a9c98c LibWeb: Serialize grid-area as auto if all sub-properties are auto 2025-03-20 16:59:27 +00:00
aplefull
57d0c563e0 LibGfx: Fix handling of partially corrupt GIFs
GIF loader was completely failing when encountering errors with
frame descriptors or individual frames, even when some frames were
successfully loaded. Now we attempt to decode at least some frames
and fail only when no frames can be decoded at all.
2025-03-20 16:12:53 +01:00
Tim Ledbetter
54351e7327 LibWeb: Use shortest serialization for shorthands with repeated values
For shorthands where all the values are repeated, we now only output
the value once.
2025-03-20 14:30:55 +01:00
Psychpsyo
528af90cd4 Meta: Make CI enforce doctype in test cases
This currently does not enforce it on Layout tests, even though
it seems most necessary there.
This is to speed up the review on this PR due to an excessive
amount of layout tests that would need rebaselining if DOCTYPEs
were added to them.
2025-03-20 11:50:49 +01:00
Psychpsyo
0b0dd7d4a5 Meta: Add DOCTYPEs to text tests that need rebaselining after
This is a separate commit from the one that adds DOCTYPEs to all
the other text tests, to make review easier.
2025-03-20 11:50:49 +01:00
Psychpsyo
fed0d6b892 Meta: Add DOCTYPEs to ref tests 2025-03-20 11:50:49 +01:00
Psychpsyo
b3487d8994 Meta: Add DOCTYPEs to most text tests 2025-03-20 11:50:49 +01:00
Psychpsyo
a5a84159a3 Meta: Add DOCTYPEs to sceenshot tests
input-placeholder-ref was modified because the input box ends up
being slightly wider outside of quirks mode.
2025-03-20 11:50:49 +01:00
Jelle Raaijmakers
bf333eaea2 CI: Only run commit linter for pull requests, not pushes
This requires us to always run the CI job and check the individual jobs'
results, since only having `needs:` will not work when `lint_commits` is
potentially skipped.
2025-03-20 11:39:29 +01:00
Jelle Raaijmakers
6f69a445bd CI: Only run builds after successful linting
We can prevent running builds unnecessarily by requiring the linters to
succeed first. If either the code or commit linter fails, it means the
author of the PR needs to rework their branch and after pushing their
changes, we need to do a full new CI run anyway.
2025-03-20 11:14:56 +01:00
Timothy Flynn
086a921213 AK: Disallow construction of JsonParser
JsonParser has a footgun where it does not retain ownership of the
string to be parsed. For example, the following results in UAF:

    JsonParser parser(something_returning_a_string());
    parser.parse();

Let's avoid this altogether by only allowing use of JsonParser with
a static, safe method.
2025-03-20 10:50:24 +01:00
Timothy Flynn
64aaf73775 LibWeb: Avoid using JsonParser directly in WebDriver
No need to construct a temporary parser.
2025-03-20 10:50:24 +01:00
Timothy Flynn
9214322129 UI/Qt: Do not make assumptions about autocomplete response types
For example, we expect a JSON array from Google. Let's not crash if we
get a JSON object or some other unexpected type.
2025-03-20 10:50:24 +01:00
Timothy Flynn
8847079d8a UI/Qt: Invert check for DuckDuckGo autocomplete parse results 2025-03-20 10:50:24 +01:00
Timothy Flynn
86a93b9b47 UI/Qt: Prevent UAF while parsing autocomplete response data
JsonParser only holds a view into the provided string, the caller must
keep it alive. Though we can actually just use JsonValue::from_string
here instead.
2025-03-20 10:50:24 +01:00
Jelle Raaijmakers
ea8213f7fa Meta: Add Open Collective to FUNDING.yml 2025-03-20 10:00:02 +01:00
Jess
12cbefbee7 LibJS+LibCrypto: Use a bitwise approach for BigInt's as*IntN methods
This speeds up expressions such as `BigInt.asIntN(0x4000000000000, 1n)`
(#3615). And those involving very large bigints.
2025-03-20 09:44:12 +01:00
Jess
92d0cd3c7c LibJS: Make InvalidIndex detail the full range of allowed values 2025-03-20 09:44:12 +01:00
Timothy Flynn
daca9f5995 LibDevTools+LibWebView+WebContent: Selectively fetch DOM node properties
When we inspect a DOM node, we currently serialize many properties for
that node, including its layout, computed style, used fonts, etc. Now
that we aren't piggy-backing on the Inspector interface, we can instead
only serialize the specific information required by DevTools.
2025-03-20 09:01:26 +01:00
Timothy Flynn
19529590b9 LibDevTools+WebContent: Simplify sending box-model properties a bit
Now that we aren't piggy-backing on the Inspector interface, we can make
our box-model serialization provide exactly the values that DevTools
requires.
2025-03-20 09:01:26 +01:00
Aliaksandr Kalenik
1f8e7c3cca LibWeb/Layout: Improve grid item sizing for replaced boxes
With this change we no longer stretch "width: auto" for replaced
elements and also use "width calculation rules for block-level replaced
elements", like suggested by the spec.
2025-03-20 03:36:56 +01:00
stasoid
2dd657f530 LibWebView: Port to Windows 2025-03-19 20:25:24 -06:00
stasoid
2abc792938 LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
stasoid
2e200489c8 LibCore: Implement StandardPaths::user_data_directory on Windows 2025-03-19 20:25:24 -06:00
stasoid
10db20a537 LibCore: Implement System::current_executable_path on Windows 2025-03-19 20:25:24 -06:00
Andrew Kaster
ddcd48d12e Documentation: Update build instructions to remove -GXcode suggestion
Also some other assorted docs cleanup.
2025-03-19 20:42:16 -04:00
Psychpsyo (Cameron)
2f6de5d9ac LibWeb: Import typo fix from the spec 2025-03-19 17:36:48 +00:00
Tim Ledbetter
5d57723ebf LibWeb: Implement CSSImportRule.supportsText
Returns the supports condition specified by the given import at-rule.
2025-03-19 16:42:51 +01:00
Tim Ledbetter
c37a47f76f LibWeb/CSS: Implement import at-rule supports conditions
This indicates the features the browser must support for the given
stylesheet to be fetched.
2025-03-19 16:42:51 +01:00
Tim Ledbetter
d38b5e260e LibWeb: Mark CSSImportRule.styleSheet IDL definition as nullable
The stylesheet may be null if its `supports()` condition does not match.
This matches the current specification.
2025-03-19 16:42:51 +01:00
Timothy Flynn
942f26a846 LibWebView: Remove now-unused ProcessManager HTML generator 2025-03-19 10:03:17 -04:00
Timothy Flynn
45d8cd5c9f UI/Qt: Replace the Task Manager window with about:processes 2025-03-19 10:03:17 -04:00
Timothy Flynn
67a1dd72db UI/AppKit: Replace the Task Manager window with about:processes 2025-03-19 10:03:17 -04:00
Timothy Flynn
843209c6a9 LibWeb+LibWebView+WebContent: Add an about:processes page
The intent is that this will replace the separate Task Manager window.
This will allow us to more easily add features such as actual process
management, better rendering of the process table, etc. Included in this
page is the ability to sort table rows.

This also lays the ground work for more internal `about` pages, such as
about:config.
2025-03-19 10:03:17 -04:00
Timothy Flynn
9dcbf5562a LibWeb: Extract some Internals functionality to a base class
This will just allow re-using these definitions on other internal pages.
2025-03-19 10:03:17 -04:00
Sam Atkins
2d220a8bbc LibWeb: Return CSSStyleProperties as a GC::Ref 2025-03-19 13:53:00 +00:00
Sam Atkins
9b06f66571 LibWeb/CSS: Return GC::Ref from Parser::convert_to_style_declaration() 2025-03-19 13:53:00 +00:00
Sam Atkins
a28197669a LibWeb/CSS: Move property code from CSSStyleDeclaration to *Properties
CSSStyleDeclaration is a base class that's used by various collections
of style properties or descriptors. This commit moves all
style-property-related code into CSSStyleProperties, where it belongs.

As noted in the previous commit, we also apply the CSSStyleProperties
prototype now.
2025-03-19 13:53:00 +00:00
Sam Atkins
83bb92c4e0 LibWeb/CSS: Merge style declaration subclasses into CSSStyleProperties
We previously had PropertyOwningCSSStyleDeclaration and
ResolvedCSSStyleDeclaration, representing the current style properties
and resolved style respectively. Both of these were the
CSSStyleDeclaration type in the CSSOM. (We also had
ElementInlineCSSStyleDeclaration but I removed that in a previous
commit.)

In the meantime, the spec has changed so that these should now be a new
CSSStyleProperties type in the CSSOM. Also, we need to subclass
CSSStyleDeclaration for things like CSSFontFaceRule's list of
descriptors, which means it wouldn't hold style properties.

So, this commit does the fairly messy work of combining these two types
into a new CSSStyleProperties class. A lot of what previously was done
as separate methods in the two classes, now follows the spec steps of
"if the readonly flag is set, do X" instead, which is hopefully easier
to follow too.

There is still some functionality in CSSStyleDeclaration that belongs in
CSSStyleProperties, but I'll do that next. To avoid a huge diff for
"CSSStyleDeclaration-all-supported-properties-and-default-values.txt"
both here and in the following commit, we don't apply the (currently
empty) CSSStyleProperties prototype yet.
2025-03-19 13:53:00 +00:00
Sam Atkins
687d32b712 LibWeb: Remove ElementInlineCSSStyleDeclaration entirely
All of its behavior has now been moved up into its parent classes.
2025-03-19 13:53:00 +00:00
Sam Atkins
50455c2f5e LibWeb: Stop constructing temporary ElementInlineCSSStyleDeclarations
Previously, parse_css_style_attribute() would parse the string, extract
the properties, add them to a newly-created
ElementInlineCSSStyleDeclarations, and then user code would take the
properties back out of it again and throw it away. Instead, just return
the list of properties, and the caller can create an EICSD if it needs
one.
2025-03-19 13:53:00 +00:00
Sam Atkins
f0d198ca3f LibWeb/CSS: Move CSSStyleDeclaration subclasses' fields into it
The spec defines several properties on the declaration which we
previously made virtual or stored on subclasses. This commit moves these
into CSSStyleDeclaration itself, and updates some of the naming.
2025-03-19 13:53:00 +00:00
Sam Atkins
3425aa0737 LibWeb/DOM: Introduce an ElementReference type
We have the "Element, but also maybe a pseudo-element of it" concept in
a lot of places, so let's wrap it up in a single type to make it easier
to deal with.
2025-03-19 13:53:00 +00:00
Sam Atkins
dea5fde3f9 LibWeb/HTML: Fix source insertion/removal steps
Corresponds to be5f269ca8

We don't yet implement "moving steps" so that's left for when we do.
2025-03-19 13:52:20 +00:00
Jelle Raaijmakers
c2e21d33eb LibWeb: Do not calculate corner radii if no radius is set
The `as_corner()` and `floored_device_pixels()` functions popped up
frequently in profiles when selecting text on some Tweakers.net pages.
For every corner we're performing multiple device pixel calculations
regardless of whether any radius was actually set.

Add an early return if no radius is set. On my machine this reduces the
time taken in both `as_corner()` and `floored_device_pixels()` by 46%
(63% fewer calls).
2025-03-19 14:22:10 +01:00
devgianlu
cfeb916e61 LibWeb: Remove unused underlying_buffer_source function
This function is not used anywhere and will most likely end up causing
problems so just remove it.
2025-03-19 13:46:50 +01:00
devgianlu
033ba43faf LibWeb: Use get_buffer_source_copy for getting the actual byte buffer
`WebIDL::underlying_buffer_source` gets the underlying buffer source
which is not resized according to, for example, `subarray`.
2025-03-19 13:46:50 +01:00
devgianlu
e02521911a LibWeb: Refactor {Dec,C}ompressionStream to handle split chunks 2025-03-19 13:46:50 +01:00
devgianlu
2b3934e34e LibCrypto: Remove leftover checksum helpers 2025-03-19 13:46:50 +01:00
devgianlu
f3631d6517 LibCrypto: Remove unused cksum class 2025-03-19 13:46:50 +01:00
devgianlu
6b2515657c LibCrypto: Remove unused CRC32, CRC16 and CRC8 classes 2025-03-19 13:46:50 +01:00
devgianlu
0561d130f3 LibCrypto: Remove unused Adler32 class 2025-03-19 13:46:50 +01:00
devgianlu
1c2b373e9c LibCompress: Refactor deflate de/compressor using zlib
Also remove two crash tests that are not relevant anymore because the
implementation changed substantially.
2025-03-19 13:46:50 +01:00
devgianlu
2baa7977a4 LibCompress: Refactor gzip de/compressor using zlib 2025-03-19 13:46:50 +01:00
devgianlu
dafbe32626 LibCompress: Refactor zlib de/compressor using zlib 2025-03-19 13:46:50 +01:00
devgianlu
c4b76bea13 LibCompress: Introduce generic de/compressor using zlib
This compressor decompressor is capable of handling zlib, gzip and
deflate all in one.
2025-03-19 13:46:50 +01:00
devgianlu
1c836588d9 LibWeb: Add some compression WPT tests
These are relevant for the next commits.
2025-03-19 13:46:50 +01:00
devgianlu
1612c1688e LibWeb: Change hardcoded compression test to round trip
As compression is not always deterministic, we cannot hardcode what
it'll be like, do a round trip instead.
2025-03-19 13:46:50 +01:00
devgianlu
3d3e77cd3e Meta: Add explicit vcpkg dependency for zlib
zlib is already included transitively for other dependencies, include it
explicitly and link it with `LibCompress`.
2025-03-19 13:46:50 +01:00
Sam Atkins
d5b9c39a98 LibWeb: Replace webkit meter-state pseudo-elements with pseudo-classes
This also implements the `:high-value` and `:low-value` that are in the
spec.

Same note as before about this being based on the very-drafty CSS Forms
spec. In fact, some of this isn't even in that spec yet. Specifically,
the `:suboptimal-value` and `:even-less-good-value` names are undecided
and subject to change. However, it's clear that this is a pseudo-class
situation, not a pseudo-element one, so I think this is still an
improvement, as it allows styling of the `::fill` pseudo-element
regardless of what state it is in.

Relevant spec issue: https://github.com/openui/open-ui/issues/1130
2025-03-19 10:10:03 +00:00
Sam Atkins
1978578a72 LibWeb: Expose HTMLMeterElement's optimum/suboptimum/etc state
No behaviour change, but this will allow us to switch over to
pseudo-classes for this state.
2025-03-19 10:10:03 +00:00
Sam Atkins
4c3c907041 LibWeb: Implement progress/range-input accent color in CSS
The `AccentColor` keyword does this in a simpler way, and allows authors
to override it.
2025-03-19 10:10:03 +00:00
Sam Atkins
3ebdb64fed LibWeb: Replace ::-webkit pseudo-elements with ones from CSS Forms spec
This spec is very early on, and likely to change. However, it still
feels preferable to use these rather than the prefixed -webkit ones.

Plus, as we have a `::fill` on range inputs, we can use that for styling
the bar instead of inserting CSS from C++.
2025-03-19 10:10:03 +00:00
Jess
f5a6704219 LibJS: Fix UAF in ECMAScriptFunctionObject::internal_construct
Currently, we create `this_argument` with
`ordinary_create_from_constructor`, then we use `arguments_list` to
build the callee_context.

The issue is we don't properly model the side-effects of
`ordinary_create_from_constructor`, if `new_target` is a proxy object
then when we `get` the prototype, arbitrary javascript can run.

This javascript could perform a function call with enough arguments to
reallocate the interpreters m_argument_values_buffer vector. This is
dangerous and leads to a use-after-free, as our stack frame maintains a
pointer to m_argument_values_buffer (`arguments_list`).
2025-03-19 10:31:00 +01:00
Aliaksandr Kalenik
b8fa355a21 LibWeb: Implement "transferred size suggestion" part of GFC spec 2025-03-19 10:21:54 +01:00
Tim Ledbetter
f0917ea150 LibWeb: Ensure shortest serialization is used for grid-column values 2025-03-19 02:08:05 +01:00
Tim Ledbetter
6811264b11 LibWeb: Ensure shortest serialization is used for grid-row values 2025-03-19 02:08:05 +01:00
Tim Ledbetter
83143e3018 LibWeb: Avoid repetition when serializing grid track placement values 2025-03-19 02:08:05 +01:00
Luke Wilde
7643a079c0 LibWeb: Enforce Content Security Policy of Fetch responses 2025-03-19 00:55:14 +01:00
Luke Wilde
51796e2d3a LibWeb: Report CSP violations for request 2025-03-19 00:55:14 +01:00
Luke Wilde
6f771f45e2 LibWeb: Enforce Content Security Policy on Fetch requests 2025-03-19 00:55:14 +01:00
Luke Wilde
86170f4bfd LibWeb/CSP: Introduce the ability to create and report a violation
A violation provides several details about an enforcement failing, such
as the URL of the document, the directive that returned "Blocked", etc.
2025-03-19 00:55:14 +01:00
Luke Wilde
02236be737 LibWeb/CSP: Implement SecurityPolicyViolationEvent
This is used to report violations of policies to the element/global
object that caused it.
2025-03-19 00:55:14 +01:00
Aliaksandr Kalenik
564cd1849b Tests: Disable css/css-lists/list-style-type-string-004.html
259d39cb was not enough to make this test pass reliably, so let's
disable it back for now.
2025-03-19 00:26:40 +01:00
Andrew Kaster
89ecc75ed8 LibCore+Meta: Un-break Swift build on Linux
LibCore's list of ignored header files for Swift was missing the Apple
only files on non-Apple platforms. Additionally, any generic glue code
cannot use -fobjc-arc, so we need to rely on -fblocks only.
2025-03-18 17:15:08 -06:00
Andrew Kaster
01ac48b36f AK: Support storing blocks in AK::Function
This has two slightly different implementations for ARC and non-ARC
compiler modes. The main idea is to store a block pointer as our
closure and use either ARC magic or BlockRuntime methods to manage
the memory for the block. Things are complicated by the fact that
we don't yet force-enable swift, so we can't count on the swift.org
llvm fork being our compiler toolchain. The patch adds some CMake
checks and ifdefs to still support environments without support
for blocks or ARC.
2025-03-18 17:15:08 -06:00
Andrew Kaster
72acb1111f CMake: Add find module for BlocksRuntime on non-Apple platforms 2025-03-18 17:15:08 -06:00
Andrew Kaster
be84ff4f2c AK: Add cast using objective-c __bridge qualifier 2025-03-18 17:15:08 -06:00
Andrew Kaster
0c2f434e69 AK: Add feature detection for -fblocks and -fobjc-arc 2025-03-18 17:15:08 -06:00
Andrew Kaster
1148116a87 CMake: Allow passing test name to serenity_test
This forwards to lagom_test. One day we should simplify this..
2025-03-18 17:15:08 -06:00
Tim Ledbetter
f6a8e5aa68 LibWeb: Use correct canonical serialization for BorderRadiusStyleValue 2025-03-18 21:55:06 +01:00
Tim Ledbetter
85728b297f LibWeb: Ensure the shortest serialization is used for border-radius
This implementation also fixes an issue where the individual components
of the `border-radius` shorthand were always assumed to be of type
`BorderRadiusStyleValue`, which could lead to a crash when CSS-wide
keywords were used.
2025-03-18 21:55:06 +01:00
Tim Ledbetter
040dca0223 AK: Add first_is_equal_to_all_of()
This method returns true if all arguments are equal.
2025-03-18 21:55:06 +01:00
Sam Atkins
97e917bdf5 LibWeb/CSS: Allow bare zero for gradient angles
Corresponds to f952e97da9
2025-03-18 20:04:08 +00:00
Timothy Flynn
4dfc29356d LibWeb: Initialize the Storage byte count upon creation
A Storage object may be created with an existing storage bottle. For
example, if you navigate from site.com/page1 to site.com/page2, they
will have different localStorage objects, but will use the same bottle
for actual storage.

Previously, if page1 set some key/value item, we would initialize the
byte count to 0 on page2 despite having a non-empty bottle. Thus, if
page2 set a smaller value with the same key, we would overflow the
computed byte count, and all subsequent writes would be rejected.

This was seen navigating from the chess.com home page to the daily
puzzle page.
2025-03-18 20:34:13 +01:00
Aliaksandr Kalenik
31da70bbfc Tests/LibWeb: Enable some tests relying on "reftest-wait" 2025-03-18 20:09:46 +01:00
Aliaksandr Kalenik
259d39cbad UI/Headless: Wait for "reftest-wait" class removal before screenshotting
Resolves https://github.com/LadybirdBrowser/ladybird/issues/3984
2025-03-18 20:09:46 +01:00
Aliaksandr Kalenik
394073f611 LibWeb: Rename internals.signalTextTestIsDone() to signalTestIsDone()
In upcoming change this function will be used for ref-tests as well.
2025-03-18 20:09:46 +01:00
Alec Murphy
101a8aef26 LibWeb: Use Super on macOS for page scroll/nav
On macOS, we should use the Cmd (Super) modifier key along with the
arrow keys to scroll to the beginning/end of the document, or navigate
back and forth in the history, rather than the Ctrl or Alt keys.
2025-03-18 15:07:09 -04:00
Shannon Booth
894c51e8e7 LibWeb/HTML: Handle missing second component in datetime-local
We were previously not checking for EOF which meant we were not
handling seconds being missing in the time component.
2025-03-18 15:05:02 -04:00
Shannon Booth
a457ebeec5 LibWeb/HTML: Implement 'convert string to number' for datetime-local 2025-03-18 15:05:02 -04:00
Timothy Flynn
780de1395b LibJS: Merge Intl.DurationFormat style and display fields into a struct
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/d56d624
2025-03-18 11:47:23 -04:00
Timothy Flynn
00d00b84d3 LibJS: Ensure relevant extension keys are included in ICU locale data
This is a normative change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/7508197

In our implementation, we don't have the affected AOs directly, as we
delegate to ICU. So instead, we must ensure we provide ICU a locale with
the relevant extension keys present.
2025-03-18 11:47:23 -04:00
Timothy Flynn
37b8ba96f1 LibJS: Use currency digits for NumberFormat only for standard notation
This is a normative change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/9140da2
2025-03-18 11:47:23 -04:00
Timothy Flynn
96c059bf67 LibJS: Use correct enum casing in some Intl constructors 2025-03-18 11:47:23 -04:00
Timothy Flynn
ea10470071 LibJS: Correctly print labels for some Intl objects
For example, printing an Intl.Collator object would previously display:

    [Intl.Collator]  numeric:
    "en"  locale:
    "sort"  usage:
    "variant"  sensitivity:
    "upper"  caseFirst:
    "default"  collation:
    false  ignorePunctuation:
    false

We now print:

    [Intl.Collator]
      locale: "en"
      usage: "sort"
      sensitivity: "variant"
      caseFirst: "upper"
      collation: "default"
      ignorePunctuation: false
      numeric: false
2025-03-18 11:47:23 -04:00
Sam Atkins
6d3534ae9c Tests: Disable fDAT-inherits-cICP.html test that uses "reftest-wait"
We don't support this mechanism in our test runner yet, which makes this
test flaky.
2025-03-18 14:56:02 +00:00
Aliaksandr Kalenik
4a7b947c5d LibWeb: Clamp content-based minimum size by limited max track size [GFC]
Progress on https://wpt.live/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
2025-03-18 15:01:02 +01:00
Shannon Booth
ec3c545426 LibURL+LibWeb: Ensure opaque paths always roundtrip
Corresponds to: https://github.com/whatwg/url/commit/6c782003
2025-03-18 12:17:19 +00:00
Tim Ledbetter
01d1a9528b LibWeb: Calculate the correct resolved value for inset properties
This improves the output of `getComputedStyle()` for the `top`,
`bottom`, `left` and `right` properties, where the used value is now
returned rather than the computed value, where applicable."
2025-03-18 09:27:51 +00:00
Shannon Booth
2022c9e679 Tests/LibWeb: Import the WPT URL test suite 2025-03-18 10:00:33 +01:00
Andrew Kaster
20890d7b70 Meta: Add fontconfig and freetype vcpkg overlays
Temporary until their canonical git forge is back up and running
2025-03-18 00:25:42 -06:00
Shannon Booth
b8adf193f5 LibWeb/SVG: Work around no layout node in SVGCircleElement::get_path
This is clearly not the correct fix, but instead of crashing let's
log an error and bail.

Works around a crash seen on both:

 * https://reddit.com
 * https://www.w3.org/TR/web-animations-1 (#879)
2025-03-17 20:10:11 +01:00
mikiubo
c85df78c4c LibRegex: Remove orphaned save points in nested LookAhead 2025-03-17 16:11:02 +01:00
stasoid
a6935299eb LibWeb: Correctly calculate static position rect when absolutely
positioned element is a descendant of inline-block

Sets inline block offsets in InlineFormattingContext.cpp, but this is
not enough. When static position rect is calculated during layout,
not all ancestors of abspos box may have their offsets calculated yet
(more info here: https://github.com/LadybirdBrowser/ladybird/pull/2583#issuecomment-2507140272).
So now static position rect is calculated relative to static containing
block during layout and calculation relative to actual containing block
is done later in
FormattingContext::layout_absolutely_positioned_element.

Fixes wpt/css/CSS2/abspos/static-inside-inline-block.html
2025-03-17 15:55:06 +01:00
Tim Ledbetter
1821896ecf LibWeb: Implement the HTMLLinkElement.sheet attribute
This returns the link element's associated style sheet.
2025-03-17 14:47:20 +01:00
Sam Atkins
db597843d6 LibWeb/CSS: Correct parsing of @supports selector()
A couple of fixes here:
- Parse a `<complex-selector>` instead of a `<selector-list>`
- Don't match if any unknown `::-webkit-*` pseudo-elements are found
2025-03-17 10:00:19 +00:00
Sam Atkins
b6fb4baeb7 LibWeb/CSS: Implement @supports font-format() and font-tech()
These let authors query whether we support font formats and features.
2025-03-17 10:00:19 +00:00
Sam Atkins
adfe8a9dcb LibWeb/CSS: Add functions that report font format/technology support
Both `@supports` and `@font-face` need this. There may be some automatic
way of querying whether our renderer supports these, but I couldn't
figure it out, so here's a basic hard-coded list. I think the font-tech
list has false negatives, as I don't know enough about fonts to
determine what we support accurately.
2025-03-17 10:00:19 +00:00
Sam Atkins
1e6f703b30 LibWeb/CSS: Compare MediaFeatureValues using references not copies 2025-03-17 10:00:19 +00:00
Sam Atkins
e125ab360e LibWeb/CSS: Merge MediaFeature data members
A MediaFeature either has a MediaFeatureValue, or a Range, or nothing.
Combining these into a Variant reduces the size from 176 bytes to 128,
and also makes constructing these a little less awkward.
2025-03-17 10:00:19 +00:00
Sam Atkins
0f5e054f97 LibWeb: Implement generic boolean logic for media/supports queries
CSS Values 5 now defines a `<boolean-expr[]>` type that is used in place
of the bespoke grammar that previously existed for `@media` and
`@supports` queries. This commit implements some BooleanExpression
types to represent the nodes in a `<boolean-expr[]>`, and reimplements
`@media` and `@supports` queries using this.

The one part of this implementation I'm not convinced on is that the
`evaluate()` methods take a `HTML::Window*`. This is a compromise
because `@media` requires a Window, and `@supports` does not require
anything at all. As more users of `<boolean-expr[]>` get implemented in
the future, it will become clear if this is sufficient, or if we need
to do something smarter.

As a bonus, this actually improves our serialization of media queries!
2025-03-17 10:00:19 +00:00
Sam Atkins
84a695c958 LibWeb/CSS: Evaluate Supports query components during parsing
Instead of parsing the parts of a `@supports` query, then only
evaluating them when constructing the Supports itself, we can instead
evaluate them as we parse them. This simplifies things as we no longer
need to pass a Realm around, and don't have to re-parse the conditions
again with a new Parser instance.
2025-03-17 10:00:19 +00:00
Sam Atkins
95730c66aa LibWeb: Make non-replaced flex items make use of transferred size
Corresponds to 9beaea1f2a
2025-03-17 09:35:58 +00:00
Sam Atkins
3dd079b308 LibWeb/HTML: Add stub for WebDriver BiDi to intercept file dialogs
Corresponds to 09ad1b9894
2025-03-17 09:34:48 +00:00
Piotr Bartoszewicz
7a2cc28932 Nix: Change incorrect package name in /Toolchain/Nix/shell.nix 2025-03-16 15:30:33 -06:00
Aliaksandr Kalenik
2e256d2eac LibWeb: Invalidate text-decoration-thickness as paint-only property
Fixes underinvalidation caused by resolving text-decoration-thickness
during layout commit, while this property can be invalidated
independently of layout.
2025-03-16 22:25:26 +01:00
Luke Wilde
61c1e4a855 LibWebView: Keep javascript URL navigations in the same process
JavaScript URLs run in the same document context the navigation was
started in, so they're not eligible to be moved to a new WebContent
process.

Fixes the "Login as demo user" link on https://demo.immich.app/
2025-03-16 10:59:41 -04:00
Andrew Kaster
c8787e6a9f LibCore: Add swift bindings for EventLoop as an Executor and Actor 2025-03-15 21:51:22 -06:00
Timothy Flynn
3af63bc5a3 Everywhere: Replace miscellaneous references to the chrome process 2025-03-15 19:57:27 -04:00
Timothy Flynn
d94bb99c50 Documentation: Remove outdated comment on using the Qt UI for WPT
We now run the tests headlessly.
2025-03-15 19:57:27 -04:00
Timothy Flynn
18eee7e3f0 LibWebView: Rename the Chrome process type to Browser 2025-03-15 19:57:27 -04:00
Timothy Flynn
e20d7be15f LibWeb+UI: Rename ChromeInputData to BrowserInputData 2025-03-15 19:57:27 -04:00
Timothy Flynn
47d6747945 LibWebView+UI: Rename ChromeProcess to BrowserProcess 2025-03-15 19:57:27 -04:00
Timothy Flynn
e00c0c176e LibWebView+UI: Rename ChromeOptions to BrowserOptions 2025-03-15 19:57:27 -04:00
Timothy Flynn
6078143241 LibWeb+WebContent: Remove "chrome" from generated page template strings 2025-03-15 19:57:27 -04:00
Timothy Flynn
9de6987134 Documentation: Update steps to enable DevTools via the UI 2025-03-15 19:09:40 +01:00
Timothy Flynn
0065dde749 UI/Qt: Add UI components to enable DevTools at runtime 2025-03-15 19:09:40 +01:00
Timothy Flynn
28574e2812 UI/AppKit: Add UI components to enable DevTools at runtime 2025-03-15 19:09:40 +01:00
Timothy Flynn
df7917d705 LibWebView: Change the DevTools server to be a runtime-enabled feature 2025-03-15 19:09:40 +01:00
Timothy Flynn
810d04b3f4 LibWeb+LibWebView+WebContent: Remove the built-in Inspector 2025-03-15 19:09:40 +01:00
Timothy Flynn
1c696e7893 UI/Qt: Remove the built-in Inspector widget 2025-03-15 19:09:40 +01:00
Timothy Flynn
03735cf11d UI/AppKit: Remove the built-in Inspector widget 2025-03-15 19:09:40 +01:00
Mehran Kamal
bb87de58a0 LibWeb+LibGfx: Paint line_cap, line_join for Canvas Strokes 2025-03-15 14:02:27 +01:00
Mehran Kamal
12968ff025 LibGfx: Move to_skia_cap, to_skia_join to SkiaUtils 2025-03-15 14:02:27 +01:00
Aliaksandr Kalenik
23151de217 LibWeb/Layout: Fix min{max}-content size calculation for grid items
Instead of directly invoking `to_px()`,
`calculate_min_content_contribution()` needs to use
`calculate_inner_width()` and `calculate_inner_height()`, which are
aware of how to correctly handle `min-content` and `max-content` values.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3469
2025-03-15 13:51:16 +01:00
Aliaksandr Kalenik
08c155cd3f LibWeb: Resolve "height: auto" using preferred aspect ratio if possible
Fixes https://github.com/LadybirdBrowser/ladybird/issues/2276
2025-03-15 13:51:16 +01:00
Aliaksandr Kalenik
227b4c38b7 LibWeb: Use parent's available space for anonymous blocks in BFC
Height resolution assumes that when available space is definite, it
matches the size of non-anonymous containing block. With this change, we
correctly maintain this assumption when box is wrapped in anonymous
node.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3422
2025-03-15 13:31:07 +01:00
Aliaksandr Kalenik
9e287465b9 LibWeb: Fix CSS transform invalidation when transitioning to none
Fixes https://github.com/LadybirdBrowser/ladybird/issues/2707
2025-03-15 13:30:45 +01:00
Shannon Booth
a9e20cb6c3 LibURL/Pattern: Use ConstructorStringParser to construct URLPatternInit 2025-03-15 07:39:03 -04:00
Shannon Booth
e369756e9c LibURL/Pattern: Implement the constructor string parser
This is missing one small bit of functionality where the not-yet
impplemented component compilation is required.
2025-03-15 07:39:03 -04:00
Shannon Booth
f05c0509c3 AK: Add ability to check Optional equality with an OptionalNone
While we don't want to be writing this type of code in 'normal'
code this is useful to do in tests as:

EXPECT_EQ(my_optional, OptionalNone {});

Has a much better error on assertion failure when compared with:

EXPECT(!my_optional.has_value());
2025-03-15 07:39:03 -04:00
Shannon Booth
e70272ddef LibURL/Pattern: Implement URL Pattern canonicalization
These are used to normalize URL components.
2025-03-15 07:39:03 -04:00
Shannon Booth
f775ee8a93 LibURL: Rename 'cannot be a base URL' state to 'opaque path' state
This follows a rename made in the URL specification.
2025-03-15 07:39:03 -04:00
Shannon Booth
f8f21319f9 LibURL/Pattern: Implement the URL Pattern Tokenizer
The tokenizer is used for both pattern string and constructor string
parsing of URL Patterns.
2025-03-15 07:39:03 -04:00
Sam Atkins
70e3a48892 LibWeb: Stub out "focus-without-user-activation" feature policy
For now this always returns that focus is allowed, as that matches our
previous behavior.

Corresponds to d7053d86ad
2025-03-14 20:33:25 +00:00
Sam Atkins
7902d13c28 LibWeb/HTML: Add FIXMEs for CanvasTextDrawingStyle lang attribute
Corresponds to aa586d0ba9
2025-03-14 20:33:25 +00:00
Sam Atkins
f1c88000da LibWeb/HTML: Early-out of input activation behavior for immutable inputs
The spec text change corresponds to e6e914d086

But while I'm here I might as well just implement it. :^)
2025-03-14 20:33:25 +00:00
Sam Atkins
6b8adb522c LibWeb: Set iframe border to 0px when frameborder attribute is invalid
Corresponds to 6e19cef90e
2025-03-14 20:33:25 +00:00
Sam Atkins
415dd1be06 LibWeb/HTML: Remove "flag" word from usage of "page showing"
Corresponds to 30935f3474
2025-03-14 20:33:25 +00:00
Tim Ledbetter
b9ac99d2eb Revert "LibRegex: Remove orphaned save points in nested LookAhead"
This reverts commit f2678bfcb8.
2025-03-14 19:57:33 +00:00
Timothy Flynn
0a5f68eba6 LibWebView: Disable site isolation and spare processes when debugging
These features make it difficult to debug a single WebContent instance.
2025-03-14 18:53:50 +01:00
Sam Atkins
0efd1729af LibWeb/HTML: Update navigation request's reserved client
Fill in a couple of FIXMEs to discard an old reserved client, and/or
create a new one, in `create_navigation_params_by_fetching()`.
2025-03-14 18:05:42 +01:00
Sam Atkins
5a4f15d8f5 LibWeb/HTML: Add environment discarding steps
Exactly one place seems to define these at the moment: service worker
clients. Since we don't have a type for these and just use
EnvironmentSettingsObject, I've put it there.
2025-03-14 18:05:42 +01:00
Sam Atkins
a15a55e858 WebWorker: Correct name of inside settings variable
The spec calls this `inside settings` so calling it `inner_settings` was
a bit confusing.
2025-03-14 18:05:42 +01:00
Timothy Flynn
9586a7500c LibWeb: Protect audio codec callbacks against its own destruction
The plugin may go out of scope before the callbacks we've queued have
fired. It is undefined behavior for these callbacks to access the plugin
data after that has occurred.

This patch protects these callbacks with weak pointers. Note that the
plugin is not ref-counted, so we cannot use `strong_ref` here.
2025-03-14 12:02:29 -05:00
Tim Ledbetter
e011ddd368 LibWeb/CSS: Parse border-block-* properties
This doesn't currently honor `writing-mode`, `direction` and
`text-orientation`.
2025-03-14 16:09:10 +00:00
Tim Ledbetter
cd1bba353a LibWeb/CSS: Parse border-inline-* properties
This doesn't currently honor `writing-mode`, `direction` and
`text-orientation`.
2025-03-14 16:09:10 +00:00
Tim Ledbetter
18cccd7633 LibWeb/CSS: Don't allow negative values in border-radius property 2025-03-14 15:07:57 +00:00
Tim Ledbetter
632fc73643 LibWeb/CSS: Don't allow negative border radius in box-shadow property 2025-03-14 15:07:57 +00:00
Tim Ledbetter
dc58c11217 LibWeb: Reject invalid background-position-* property values 2025-03-14 15:07:57 +00:00
Tim Ledbetter
764b80a1cc LibWeb/CSS: Reject radial-gradient functions with negative size 2025-03-14 15:07:57 +00:00
mikiubo
f2678bfcb8 LibRegex: Remove orphaned save points in nested LookAhead 2025-03-14 09:41:41 +01:00
Timothy Flynn
80d7350ee5 LibDevTools: Ensure the walker actor only displays nodes it created
The NodeIdentifier struct essentially contains the DOM node ID within
its WebContent process. These will repeat across multiple processes,
thus we cannot use them to search for node actors in the global actor
registry.

Instead, we can store a map of all node actors created by the walker
itself. The NodeIdentifier is then appropriate for actor lookups on
that map. This has the added benefit of not needing to search the entire
actor registry many times while forming the DOM node caches.

This fix allows us to inspect multiple tabs at once.
2025-03-14 09:04:03 +01:00
stelar7
664c57af16 LibWeb/IDB: Implement IDBFactory::databases() 2025-03-14 08:54:39 +01:00
Tim Ledbetter
5559c3cb4f LibWeb/CSS: Parse <single-transition-property> as a <custom-ident>
The specification also treats a transition name of `none` as invalid.
2025-03-14 08:52:25 +01:00
Tim Ledbetter
6298ec6be4 LibWeb: Validate time values when parsing transition value 2025-03-14 08:52:25 +01:00
Tim Ledbetter
37eb2be348 LibWeb/CSS: Disallow negative time values for transition-duration 2025-03-14 08:52:25 +01:00
Tim Ledbetter
b80c0d2114 LibWeb/CSS: Reject invalid grid track placement property values 2025-03-14 08:50:04 +01:00
Tim Ledbetter
411cafa2a9 LibMedia: Add formatter for decoder errors
This is useful for print debugging.
2025-03-14 08:48:01 +01:00
Tim Ledbetter
c270241b09 LibMedia: Propagate errors if demuxer creation fails
Previously, the browser would crash if demuxer creation failed.
2025-03-14 08:48:01 +01:00
Aliaksandr Kalenik
733d124380 LibWeb: Delete root pointer in LayoutState
It's no longer needed after we moved intrinsic sizes cache into layout
nodes.
2025-03-14 01:27:40 +01:00
rmg-x
63249ba96a LibHTTP: Add more reason phrases for 4xx response codes
https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
2025-03-14 01:23:52 +01:00
Aliaksandr Kalenik
56971a4201 LibWeb: Delete FIXME debug log in PolicyList
It adds too much spam in test runner output.
2025-03-13 22:16:47 +01:00
Timothy Flynn
0b86bcfba7 LibDevTools+LibWebView: Implement getting document style sheets 2025-03-13 16:56:28 -04:00
Timothy Flynn
cf601a49bb LibWeb+WebContent: Include rule count in listed CSS style sheets 2025-03-13 16:56:28 -04:00
Timothy Flynn
576eede2b1 LibWeb: Simplify IPC encoding of style sheet DOM node IDs
We were essentially reinventing Optional::map here.
2025-03-13 16:56:28 -04:00
Timothy Flynn
2ee3985fd1 LibDevTools+LibWebView: Implement getting the used fonts for a DOM node
This also includes a request to get all fonts for a page, which we stub
out for now as we don't have the IPC to retrieve all fonts.
2025-03-13 16:56:28 -04:00
Timothy Flynn
f9e83af475 LibDevTools: Re-implement how we handle ordered responses
We must reply to requests received from the client in the order they are
received. The wrench in this requirement is handling requests that must
be performed asynchronously, such as fetching the serialized DOM tree
from the WebContent process.

We currently handle this with a "block token". Async request handlers
hold a token that blocks any subsequent responses from being sent. When
that token is removed (i.e. the async request now has a response to be
sent), the async response is then sent followed by the blocked responses
in-order.

This strategy had a limitation that we could not handle an actor trying
to take 2 block tokens, meaning only one async request could be handled
at a time. This has been fine so far, but an upcoming feature (style
sheet sources) will break this limitation. The client will request N
sources at a time, which would try to take N block tokens.

The new strategy is to assign all requests an ID, and store a list of
request IDs that are awaiting a response. When the server wants to send
a reply, we match the ID of the replied-to message to this list of IDs.
If it is not the first in this list, then we are blocked waiting for an
earlier reply, and just store the response. When the earlier request(s)
receive their response, we can then send out all blocked replies (up to
the next request that has not yet received a response).
2025-03-13 16:56:28 -04:00
Timothy Flynn
24a5e4e7d5 LibDevTools: Move message data into a structure
This is to prepare for an upcoming change where we will need to track
replies to messages by ID. We will be able to add parameters to this
structure without having to edit every single actor subclass header
file.
2025-03-13 16:56:28 -04:00
Luke Wilde
509eaca73d LibWeb: Play audio tracks alongside video tracks with the video element
The underlying media element class already parses out the audio tracks,
regardless of the media type. Let's play them with videos!
2025-03-13 19:33:44 +01:00
Luke Wilde
4df2de2f20 LibMedia/Audio: Use duration in the container if stream doesn't have one 2025-03-13 19:33:44 +01:00
Luke Wilde
b789ba5e5f LibMedia: Demux videos with FFmpeg
This gives us access to container types other than Matroska, the
biggest one being MP4.
2025-03-13 19:33:44 +01:00
Luke Wilde
3412935a62 LibMedia: Move FFmpegIOContext into it's own file
This allows it to be reused for video.
2025-03-13 19:33:44 +01:00
Aliaksandr Kalenik
2f9d2acdb2 Tests: Disable css-contain/contain-style-remove-element-crash.html
Disabling this test because it very often crashes on CI
https://github.com/LadybirdBrowser/ladybird/issues/3894
2025-03-13 19:31:26 +01:00
Kevin Mas Ruiz
fa950a5727 LibWeb: Invalidate element with CSS custom props on attribute changes
Element styles should be invalidated when they depend on CSS variables
defined in one of their ancesors or when one of their ancestors change
their class, due to the possibility of adding new CSS variables in
scope.
2025-03-13 19:20:37 +01:00
Luke Wilde
8e1ecd25ae LibWeb: Get the correct CSP navigation type for form submission 2025-03-13 16:19:22 +01:00
Luke Wilde
819bff9ec0 LibWeb: Create policy containers from responses and then run CSP init
This allows us to parse the Content-Security-Policy header and
Referrer-Policy header from navigation responses and actually allow
them to start having an effect.
2025-03-13 16:19:22 +01:00
Luke Wilde
435f839ced LibWeb: Only stash Element's CryptographicNonce if there's a CSP header 2025-03-13 16:19:22 +01:00
Mehran Kamal
670a7ab048 LibWeb/SVG: Implement cap_style, join_style for Skia painting backend 2025-03-13 15:09:41 +01:00
stelar7
a0b252c0dd LibWeb/IDB: Update convert_a_value_to_a_key to latest changes 2025-03-13 11:23:15 +01:00
Tim Ledbetter
ad4ade3f07 LibWeb/CSS: Disallow invalid <counter-name> values
We now parse `<counter-name>` values as a `<custom-ident>`. This
disallows `default` and CSS-wide keywords as counter names. The
specification additionally disallows `none` as a counter name.
2025-03-13 05:23:19 +00:00
Aliaksandr Kalenik
76aa99a626 LibWeb: Update HTMLSlotElement subtree during partial layout tree build
Before this change, the layout tree for slots was only updated after
creating a layout node for the slot itself. This was not enough to
account for partial layout tree rebuilds when the slot content changed.
With this change, we always recurse into the slot content.

Fixes expanding and collapsing of nodes in DOM tree inspector broken in
9b26f7eb0f
2025-03-13 04:29:26 +01:00
Timothy Flynn
49adec1396 LibDevTools: Add a helper to handle asynchronous request replies
This removes some boilerplate around executing async requests, such as
calling dbgln_if on any errors, handling weak pointers to `this`, and
dealing with block tokens.
2025-03-12 12:48:05 -04:00
Timothy Flynn
e1ed8722e0 LibDevTools: Add a helper to acquire required message parameters
This is just to help make the message handlers a bit briefer. I had
considered adding a TRY-like macro to auto-return when the lookup fails,
but since statement expressions cannot return references, that would
result in a copy of all e.g. object and array lookups.
2025-03-12 12:48:05 -04:00
Timothy Flynn
4ce10f3bf4 LibDevTools: Automatically set the "from" field for server responses
The "from" field is required in every response. It is the name of the
actor sending the message. This patch fills in the "from" field in the
Actor base class so that subclasses don't have to.
2025-03-12 12:48:05 -04:00
Timothy Flynn
a7b577126a LibDevTools: Send an unknown actor error for failed DOM node lookups
DevTools will ask us to find nodes by their actor names. If the actor is
missing, we should inform DevTools of the error instead of just dropping
the request.

The diff here is a bit noisy, just due to a leftward shift of code that
used to be in an if-statement.
2025-03-12 12:48:05 -04:00
Timothy Flynn
49b964bf19 LibDevTools: Add missing return statement in the 'duplicateNode' handler 2025-03-12 12:48:05 -04:00
SINF-KEN
96a5b97131 Base: Add new error page
This commit introduces a new error page.

Co-authored-by: NotNotNescap <nescap@tuta.com>
2025-03-12 11:56:15 -04:00
Gingeh
ec1f7f87ea Base: Make about:about respect the chosen color scheme 2025-03-12 10:41:06 +00:00
Gingeh
5838c73a72 LibWeb: Restrict weird about:foo URIs
This commit:
- Prevents path traversal via the about: scheme
- Prevents loading about:inspector
- Requires about: URIs to be opaque paths
- Prevents crashes with invalid percent encoded paths
2025-03-12 10:41:06 +00:00
Tim Ledbetter
249de20343 LibWeb/CSS: Don't allow negative values in filter functions 2025-03-12 09:06:16 +00:00
Timothy Flynn
3af3799bbc WebDriver: Temporarily disable site isolation
We will need to update WebDriver to handle the switch of WebContent
processes.
2025-03-12 02:00:54 +00:00
Timothy Flynn
fce5d24e5f LibWebView+WebContent: Add a command-line flag to disable site isolation 2025-03-12 02:00:54 +00:00
Tommy van der Vorst
89f8dd9b3b Tests: Do not use data URI in css-mask-longhand test
Instead use an existing image and ensure it loads to prevent
flakiness
2025-03-11 12:16:32 -04:00
Timothy Flynn
cbefa797d4 LibDevTools+LibWebView+WebContent: Implement moving DOM nodes
This allows for click-and-dragging DOM nodes in DevTools to move them.
2025-03-11 09:50:51 -04:00
Timothy Flynn
01c44a5c66 LibDevTools+LibWebView+WebContent: Implement getting DOM node inner HTML
This is used by DevTools to copy the inner HTML to the clipboard.
2025-03-11 09:50:51 -04:00
Timothy Flynn
d75eadc3c4 LibDevTools+LibWebView+WebContent: Implement editing DOM node HTML
These commands are used for the "Edit As HTML" feature in DevTools. This
renames our existing HTML getter IPC to indicate that it is for outer
HTML. DevTools will need a separate inner HTML getter.
2025-03-11 09:50:51 -04:00
Timothy Flynn
aca4385daf LibWebView: Create a spare WebContent process
Since cross-site navigation is a pretty frequent task, creating a spare
process is commonplace in other browsers to reduce the overhead of
directing the target site to a new process.

We store this process on the WebView application. If it is unavailable,
we queue a task to create it later.
2025-03-11 12:10:42 +01:00
Timothy Flynn
5810c8073e LibWeb+LibWebView+WebContent: Begin implementing simple site islotation
Site isolation is a common technique to reduce the chance that malicious
sites can access data from other sites. When the user navigates, we now
check if the target site is the same as the current site. If not, we
instruct the UI to perform the navigation in a new WebContent process.

The phrase "site" here is defined as the public suffix of the URL plus
one level. This means that navigating from "www.example.com" to
"sub.example.com" remains in the same process.

There's plenty of room for optimization around this. For example, we can
create a spare WebContent process ahead of time to hot-swap the target
site. We can also create a policy to keep the navigated-from process
around, in case the user quickly navigates back.
2025-03-11 12:10:42 +01:00
Timothy Flynn
a34f7a5bd1 LibURL: Correctly acquire the registrable domain for a URL
We were using the public suffix of the URL's host as its registrable
domain. But the registrable domain is actually the public suffix plus
one additional label.
2025-03-11 12:10:42 +01:00
InvalidUsernameException
d0f80e1f05 Docs: Add note about Android port being broken 2025-03-10 12:58:42 -06:00
Shannon Booth
b543523717 LibWeb: Fire slotchange events when a slot is changed 2025-03-10 14:37:26 -04:00
Aliaksandr Kalenik
84ecaaa75c LibWeb: Limit sibling style invalidation by max distance
If an element is affected only by selectors using the direct sibling
combinator `+`, we can calculate the maximum invalidation distance and
use it to limit style invalidation. For example, the selector
`.a + .b + .c` has a maximum invalidation distance of 2, meaning we can
skip invalidating any element affected by this selector if it's more
than two siblings away from the element that triggered the style
invalidation.

This change results in visible performance improvement when hovering
PR list on GitHub.
2025-03-10 18:56:55 +01:00
Jelle Raaijmakers
46abdd1126 Tests: Use own websocket echo server instead of websocket.org
The public one at echo.websocket.org tends to be slow at times,
frequently causing timeouts. Ideally we would run a local websocket
server but for now we can make do with a self-hosted alternative.
2025-03-10 17:16:15 +01:00
rmg-x
6a9e637c11 LibWeb/HTML: Remove dbgln() for invalid location_url to reduce spam 2025-03-10 17:15:53 +01:00
InvalidUsernameException
d76f841994 LibWeb: Do not deform bitmaps partially outside the img-box
Instead of trying to manually determine which parts of a bitmap fall
within the box of the `<img>` element, just draw the whole bitmap and
let Skia clip the draw-area to the correct rectangle.

This fixes a bug where the entire bitmap was squashed into the rectangle
of the image box instead of being clipped.

With this change, image rendering is now correct enough to import some
of the WPT tests for object-fit and object-position. To get some good
coverage I have imported all tests for the `<img>` tag. I also wanted to
import a subset of the tests for the `<object>` tag, since those are
passing as well now. Unfortunately, they are flaky for unknown reasons.

This is the second attempt at this bugfix. The prior one was e055927ead
and broke image rendering whenever the page was scrolled. It has
subsequently been reverted in 16b14273d1. Hopefully this time it is not
horribly broken.
2025-03-10 17:14:13 +01:00
InvalidUsernameException
5d3b45127e Tests: Regression test recent image rendering bug when scrolling
e055927ead introduced a regression that caused images to not be rendered
when the page was scrolled. This was subsequently reverted in
16b14273d1. To ensure this mistake cannot happen again, this commit
introduces a regression test for that error case.
2025-03-10 17:14:13 +01:00
InvalidUsernameException
0e1eb4d4a7 LibWeb: Respect scroll position set by script during page load
When setting scroll position during page load we need to consider
whether we actually have a fragment to scroll to. A script may already
have run at that point and may already have set a scroll position.

If there is an actual fragment to scroll to, it is fine to scroll to
that fragment, since it should take precedence. If we don't have a
fragment however, we should not unnecessarily overwrite the scroll
position set by the script back to (0, 0).

Since this problem is caused by a spec bug, I have tested the behavior
in the three major browsers engines. Unfortunately they do not agree
fully with each other. If there is no fragment at all (e.g. `foo.html`),
all browsers will respect the scroll position set by the script. If
there is a fragment (e.g. `foo.html#bar`), all browsers will set the
scroll position to the fragment element and ignore the one set by
script. However, when the fragment is empty (e.g. `foo.html#`), then
Blink and WebKit will set scroll position to the fragment, while Gecko
will set scroll position from script. Since all of this is ad-hoc
behavior anyway, I simply implemented the Blink/WebKit behavior because
of the majority vote for now.

This fixes a regression introduced in 51102254b5.
2025-03-10 17:14:13 +01:00
Tim Ledbetter
53bf0ef225 LibWeb/CSS: Resolve used value for the inline-size property 2025-03-10 13:01:08 +00:00
Tim Ledbetter
1739e2851d LibWeb/CSS: Resolve used value for the block-size property 2025-03-10 13:01:08 +00:00
rmg-x
41927ad9d1 UI/Qt: Use book title capitalization for "Clear All Cookies" menu item
This follows the human interface guidelines of Ladybird.
2025-03-10 12:30:21 +00:00
rmg-x
c361ea8916 WebContent+UI/Qt: Add debug option to toggle content filtering on/off
This was needed by @piruzzolo on Discord for debugging purposes and
seems pretty useful :^)
2025-03-10 12:30:21 +00:00
rmg-x
00aa72c16e LibWeb/Loader: Add filtering_enabled flag in ContentFilter
This allows us to toggle content filtering on or off. Default is set to
true to match current behavior.
2025-03-10 12:30:21 +00:00
Tim Ledbetter
a6efdb1068 LibWeb: Treat CSS at-rule names as case-insensitive 2025-03-10 12:42:57 +01:00
sideshowbarker
4def3fe567 LibWeb: Implement string->number for type=datetime-local input elements 2025-03-10 10:34:01 +00:00
Vishal Biswas
90b303215e LibURL: Add U+005E to path percent encoding list
Passes wpt tests which were failing after
9bc33c39d4.

It also removes ^ from Userinfo set as its included in Path set now
2025-03-10 11:19:36 +01:00
rmg-x
798250d3e2 LibWeb/HTML: Remove unnecessary verification for location_url error
There is a check shortly after this, so there is no need to crash in the
event of an error.
2025-03-10 10:46:28 +01:00
Tim Ledbetter
88d35c547c LibWeb/CSS: Implement the caret-color property 2025-03-09 19:36:29 +01:00
Tim Ledbetter
bf15b7ac12 LibWeb: Treat media query with an invalid media type as invalid 2025-03-09 17:48:36 +00:00
Aliaksandr Kalenik
667cb01b60 LibWeb: Fix layout mode propagation in SVGFormattingContext 2025-03-09 18:40:37 +01:00
Aliaksandr Kalenik
92a3419799 LibWeb: Skip invalidating :first-child and :last-child if possible
There is no need to invalidate siblings affected by these pseudo classes
if invalidation reason is not insertion or removal of tree nodes.
2025-03-09 18:40:37 +01:00
Timothy Flynn
0e057d3a36 LibIPC: Don't generate "take" methods for primitive/simple types 2025-03-09 11:14:20 -04:00
Timothy Flynn
cf69f52d53 LibIPC+Everywhere: Always pass ownership of transferred data to clients
This has been a longstanding ergonomic issue with our IPC compiler. Non-
trivial types were previously passed by const&. So if we wanted to avoid
expensive copies, we would have to const_cast and move the data.

We now pass ownership of all transferred data to the client subclasses.
This allows us to remove const_cast from these methods, and allows us to
avoid some trivial expensive copies that we didn't bother to const_cast.
2025-03-09 11:14:20 -04:00
Timothy Flynn
0f05aac290 LibCore: Mark the lambda in Promise::when_resolved as mutable
This allows the handler passed into this function to also be mutable.
2025-03-09 11:14:20 -04:00
Timothy Flynn
8f6169859d LibWebSocket: Remove meaningless const&& Message constructor
This results in an ambiguity error in an upcoming commit.
2025-03-09 11:14:20 -04:00
Timothy Flynn
5f76324af5 LibDevTools+LibWebView: Take advantage of IPC encoding improvements 2025-03-09 11:14:20 -04:00
Timothy Flynn
62912b985a LibWeb+WebContent: Take advantage of IPC encoding improvements
This removes a couple of places where we were constructing strings or
vectors just to transfer data over IPC. And passes some values by const&
to remove clangd noise.
2025-03-09 11:14:20 -04:00
Timothy Flynn
68947d55d9 LibIPC: Do not require constructing containers when sending IPC messages
For example, consider the following IPC message:

    do_something(u64 page_id, String string, Vector<Data> data) =|

We would previously generate the following C++ method to encode/transfer
this message:

    void do_something(u64 page_id, String string, Vector<Data> data);

This required the caller to either have to copy the non-trivial types or
`move` them in. In some places, this meant we had to construct temporary
vectors just to send an IPC.

This isn't necessary because we weren't holding onto these parameters
anyways. We would construct an IPC::Message subclass with them (which
does require owning types), but then immediate encode the message to
an IPC::MessageBuffer and send it.

We now generate code such that we don't need to construct a Message. We
can simply encode the parameters directly without needing ownership.
This allows us to take view-types to IPC parameters.

So the above example now becomes:

    void do_something(u64, StringView, ReadonlySpan<Data>);
2025-03-09 11:14:20 -04:00
Timothy Flynn
da6c6487e5 LibIPC: Extract helper lambda to its own method
This will be needed in an upcoming commit so that this method may call
itself recursively to generate overloads. Doing this extraction ahead of
time will simply make that diff easier to grok.
2025-03-09 11:14:20 -04:00
Timothy Flynn
8277f42812 LibIPC: Remove some unnecessary newlines in generated IPC files
This isn't particularly important, but when staring at generated IPC
files, it's nice not to have an extra newline after every line of code
throughout the files.
2025-03-09 11:14:20 -04:00
Timothy Flynn
a5b996c079 LibIPC: Add a generic encoder for spans 2025-03-09 11:14:20 -04:00
Timothy Flynn
b090952274 LibIPC: Remove outdated warning about changing IPC encodings
We are no longer constrained by this LibC encoding.
2025-03-09 11:14:20 -04:00
Tim Ledbetter
6178557a07 LibWeb: Implement the HTMLInputElement.list attribute
This returns the `HTMLDataListElement` pointed to by the `list`
content attribute.
2025-03-09 15:10:55 +00:00
Ali Mohammad Pur
a37315da87 Tests: Get rid of clang-format: off in the Regex tests
Should've done this a long time ago, but now is better than never.
2025-03-09 14:37:57 +01:00
Ali Mohammad Pur
5355710481 LibRegex: Don't treat single-jump blocks as noop in the optimizer 2025-03-09 14:37:57 +01:00
Aliaksandr Kalenik
868981a46b LibWeb: Skip animation invalidation for elements nested in display none
Paper over the fact we sometimes fail to cancel animations for elements
nested in display none, and do lots of wasted work.
2025-03-09 00:06:13 +01:00
Aliaksandr Kalenik
268143681e LibWeb: Don't drop layout tree in CSS animation invalidation
It's possible to do a partial tree rebuild instead.
2025-03-09 00:06:13 +01:00
Andreas Kling
067d21b8a4 LibWeb: Don't drop entire layout tree on media query state change
This isn't actually necessary, since we already invalidate style for the
entire document, and the subsequent style update will discover any
additional layout invalidation needed as well.
2025-03-08 20:22:01 +01:00
Andreas Kling
0a300fe59b LibWeb: Update the layout tree when CSS text-transform changes
Because we cache the transformed text string in text nodes affected by
text-transform, we have to actually update the layout tree when this
property value changes.
2025-03-08 20:22:01 +01:00
Andreas Kling
def0bcdfa2 LibWeb: Don't unconditionally relayout on animation/transition changes
If a CSS animation or transition was being used to manipulate a property
that itself does not affect layout, we were still doing a full relayout
whenever any animation or transition related property was changed.

As it turns out, we can just not do that, and we avoid a bunch of
unnecessary layout work on many pages. When a layout-affecting property
is being animated, the animation/transition update code takes care to
invalidate layout as appropriate anyway!

This was very noticeable on GitHub, where moving the mouse cursor
between "Issues" and "Pull requests" would trigger a full relayout every
time. Now that doesn't happen, and it's much more responsive. :^)
2025-03-08 17:32:53 +01:00
Aliaksandr Kalenik
a4463c45b9 LibWeb: Bring back cache of intrinsic sizes across layout runs
12c6ac78e2 with fixed mistake when cache
slot is copied instead of being referenced:
```cpp
auto cache =
    box.cached_intrinsic_sizes().min_content_height.ensure(width);
```
while it should've been:
```cpp
auto& cache =
    box.cached_intrinsic_sizes().min_content_height.ensure(width);
```
2025-03-08 14:52:33 +01:00
Andreas Kling
73a4b176cf Revert "LibWeb: Cache intrinsic sizes across layout runs"
This reverts commit 12c6ac78e2.

Very large performance regression when viewing GitHub repository pages.
2025-03-08 12:08:51 +01:00
Aliaksandr Kalenik
12c6ac78e2 LibWeb: Cache intrinsic sizes across layout runs
This change moves intrinsic sizes cache from
LayoutState, which is local to current layout run,
to layout nodes, so it could be reused between
layout runs. This optimization is possible because
we can guarantee that these measurements will
remain unchanged unless the style of the element
or any of its descendants changes.

For now, invalidation is implemented simply by
resetting cache on whole ancestors chain once we
figured that element needs layout update.
The case when layout is invalidated by DOM's
structural changes is covered by layout tree
invalidation that drops intrinsic sizes cache
along with layout nodes.

I measured improvement on couple websites:
- Mail list on GMail 28ms -> 6ms
- GitHub large code page 47ms -> 36ms
- Discord chat history 15ms -> 8ms
(Time does not include `commit()`)
2025-03-08 11:45:36 +01:00
Andreas Kling
180a58b3d2 LibWeb: Don't drop entire layout tree on <input type=file> update
This was completely unnecessary, and we can just let the internal
DOM tree changes trigger partial layout updates instead.

Noticed we were repeatedly dropping layout trees on ChatGPT and this
was one of the culprits.
2025-03-08 03:37:38 +01:00
Andreas Kling
6c6f9936e2 LibWeb: Avoid more unnecessary relayouts on CharacterData text change
If the CharacterData node has no layout node when we're changing its
text, we don't need to mark the document for relayout.

This is fine, because if the node ends up getting a layout node attached
to it, we'll naturally perform relayout after that anyway.
2025-03-08 03:37:38 +01:00
Andreas Kling
267b84ebb6 LibWeb: Skip flex/grid layout when doing intrinsic sizing for ancestor
We don't need to perform inside layout of flex and grid formatting
contexts when one of their ancestors is undergoing intrinsic size
measurement. This is because the parent formatting context will have
already sized the flex/grid container, and thus inside layout is
completely redundant work.
2025-03-08 03:37:38 +01:00
Andreas Kling
6444fdf5ae LibWeb: Remove unnecessary full layout tree drop in SVGUseElement
This full invalidation was just papering over earlier bugs in the
partial layout tree update code. The DOM mutations that happen here
should be enough to drive the necessary invalidation now.

Note that this is covered by a regression test added with the
invalidation.
2025-03-08 03:37:38 +01:00
Andreas Kling
2abbf99a95 LibWeb: Add opt-in tracing of set_needs_layout() calls with reason 2025-03-08 03:37:38 +01:00
Andreas Kling
415079bc11 LibWeb: Add opt-in tracing of invalidate_layout_tree() calls with reason 2025-03-08 03:37:38 +01:00
Andreas Kling
c333042e63 LibWeb: Add opt-in tracing of update_layout() calls with reason 2025-03-08 03:37:38 +01:00
Timothy Flynn
c4b1d2382a LibDevTools+LibWebView: Implement requests to clone DOM nodes 2025-03-08 01:25:55 +01:00
Timothy Flynn
ffd48e1d45 LibDevTools+LibWebView: Implement requests to create DOM nodes
This requires a couple of amendments to the DOM node serialization.
Namely, we need to include the HTML namespace, otherwise the context
menu item to create a new node is disabled.
2025-03-08 01:25:55 +01:00
Timothy Flynn
29122786b9 LibDevTools+LibWebView: Implement requests to delete DOM nodes 2025-03-08 01:25:55 +01:00
Timothy Flynn
bdb31b029a LibDevTools+LibWebView: Implement requests to edit DOM node tags 2025-03-08 01:25:55 +01:00
Timothy Flynn
17fb21169f LibDevTools+LibWebView: Implement requests to edit DOM node attributes 2025-03-08 01:25:55 +01:00
Timothy Flynn
57e0a3f8b5 LibDevTools+LibWebView: Implement requests to edit DOM node text 2025-03-08 01:25:55 +01:00
Timothy Flynn
8bcc3d3797 LibDevTools+LibWebView: Inform the DevTools client about DOM mutations 2025-03-08 01:25:55 +01:00
Timothy Flynn
2c4b420acc LibWeb+LibWebView+WebContent: Inform the UI about DOM mutations
This will allow our DevTools server to inform the Firefox DevTools
client about DOM mutations.
2025-03-08 01:25:55 +01:00
Timothy Flynn
bf723aad98 LibWeb: Correctly set mutation record attribute namespace values
Here, we were setting the attribute_name string to the namespace string.
2025-03-08 01:25:55 +01:00
Timothy Flynn
3847d64542 LibWeb: Slightly delay queueing a character data mutation event
For DevTools, we will want to forward mutation events to the UI in order
to inform the DevTools client about changed DOM nodes. The API for this
requires the new values associated with the events; for example, for
character data events, this will be the node's new text data.

This patch moves the queueing of the mutation record until after we have
the new character data stored. This is not observable.
2025-03-08 01:25:55 +01:00
Timothy Flynn
ddea67034f LibDevTools: Associate node actors with a DOM node identifier
This is a prepatory commit to be able to handle DOM mutations. Once a
node actor is created, the DOM node it is created for must continue to
be associated with the same actor even after DOM mutations. This change
stores an identifier on the node actor, and only creates new actors when
an actor for a node does not exist.
2025-03-08 01:25:55 +01:00
Timothy Flynn
ee88edc750 LibDevTools: Add a helper to extract a DOM node JSON object more easily
The pattern of:

    auto tab = get_tab();
    auto walker = get_walker();

    if (tab && walker) {
        if (auto node = walker->dom_node(node_id)) {
            delegate().do_something(tab->description(), node);
        }
    }

Is getting a bit unergonomic and is often repeated. This patch just adds
a helper to WalkerActor to do most of this work, so now we have:

    if (auto node = WalkerActor::dom_node_for(get_walker(), node_id)) {
        delegate().do_something(node->tab->description(), node);
    }
2025-03-08 01:25:55 +01:00
Totto16
1fc5744aa4 Meta: Make gn linter actually fail
Without the `--dry-run` flag, the gn linter just formats the files in
place and reports no failure
2025-03-07 09:44:42 +01:00
Totto16
4c24e0f63d Meta: Format gn files 2025-03-07 09:44:42 +01:00
sideshowbarker
cf1425d09e LibWeb: Implement “suffering from overflow/underflow” for inputs
This change implements the requirements for the “suffering from an
overflow” and “suffering from an underflow” algorithms for
HTMLInputElement constraint validation.
2025-03-07 08:32:18 +00:00
Feng Yu
ad9f70dff9 LibWeb: Clean up unused module script fetching algorithms
This patch removes those unused 2 algorithms:
1. `fetch_internal_module_script_graph`
2. `fetch_descendants_of_a_module_script`

Those 2 algorithms were removed in spec and are not used in our
codebase.
2025-03-07 02:25:31 +01:00
Aliaksandr Kalenik
9b26f7eb0f LibWeb: Use partial layout tree rebuild in element's style invalidation
This allows us to avoid a full layout tree rebuild after change of
"display" property, which happens frequently in practice. It also
allows us to avoid a full rebuild after DOM node insertion, since
previously, computing styles for newly inserted nodes would trigger a
complete layout tree rebuild.
2025-03-06 23:48:34 +01:00
Andrew Kaster
00c9031304 RequestServer: Remove dead code from ConnectionFromClient 2025-03-06 14:43:02 -05:00
Luke Wilde
6d1f78198d LibWeb: Implement Resource Timing 2025-03-06 09:00:53 -07:00
Luke Wilde
23c84e62a5 LibWeb/Fetch: Update timing info with the timings received from RS 2025-03-06 09:00:53 -07:00
Luke Wilde
618697ef13 LibWeb: Make reference to global in report timing steps non-const
Marking a resource timing entry requires calling non-const methods on
the global object to append to the performance buffer.
2025-03-06 09:00:53 -07:00
Luke Wilde
67cfb64d07 LibWeb: Separate adding to performance buffers and queueing to observers
The User Timing, Resource Timing and Navigation Timing specifications
have not been updated to account for the queue method to also append to
the underlying performance buffer and it's method of checking it's
full.

This separates the functionality into a different function, with a flag
to indicate whether to use the custom full buffer logic or not.
2025-03-06 09:00:53 -07:00
Luke Wilde
209b10e53e RequestServer: Retrieve timing info from curl and pipe it to LibWeb
This timing info will be used to create a PerformanceResourceTiming
entry.
2025-03-06 09:00:53 -07:00
Shannon Booth
21d26c5c3e LibWeb/HTML: Implement valueAsNumber for 'time' input type 2025-03-06 09:01:18 -05:00
Shannon Booth
4bd4d777eb LibWeb/HTML: Use a helper for converting 'time' value to string
This will make it trivial to implement valueAsNumber for 'time' input
type.
2025-03-06 09:01:18 -05:00
Shannon Booth
f344eca39d LibWeb/HTML: Reuse number to date string conversion helper
This shares the code to convert to a date string for this algorithm
and the valueAsNumber implementation.
2025-03-06 09:01:18 -05:00
sideshowbarker
13f9670f20 LibWeb: Fix “step base” computation for HTMLInputElement
This change fixes a bug in our implementation of the “step base”
algorithm at https://html.spec.whatwg.org/#concept-input-min-zero. We
were using the “value” IDL/DOM attribute in a particular step, where the
spec instead actually requires using the “value” content attribute.
2025-03-06 09:00:22 -05:00
Luke Wilde
9ca25eed7f LibWeb/WebGL2: Implement EXT_color_buffer_float extension
This makes the Point Of Sale model on https://www.shopify.com/ have
colour instead of being completely black.
2025-03-06 12:59:28 +01:00
Gingeh
31853c13d3 LibWeb: Implement css gradient-interpolation-method 2025-03-06 11:33:12 +00:00
Andreas Kling
02a642b87b LibWeb: Prevent infinitely growing font size due to rem units in root
A font-size with rem units need to resolve against the default font
metrics for the root element, otherwise every time we compute style,
the reference value for rem units grows.

This fixes an issue where text on some web pages would grow every time
there was a relayout. This was very noticeable on https://proton.me/

Fixes #339
2025-03-05 22:46:06 +01:00
Aliaksandr Kalenik
dd78d5d50e LibWeb: Don't layout grid descendants in intrinsic layout mode
We already have a check to skip the layout of descendants if the
available size is intrinsic, but this is not sufficient in nested
intrinsic layout cases, where the available size might be definite even
though we are in intrinsic layout mode.
2025-03-05 21:40:59 +01:00
Aliaksandr Kalenik
b51c026f3d LibWeb: Don't layout flex descendants in intrinsic layout mode
We already have a check to skip the layout of descendants if the
available size is intrinsic, but this is not sufficient in nested
intrinsic layout cases, where the available size might be definite even
though we are in intrinsic layout mode.
2025-03-05 21:40:59 +01:00
Timothy Flynn
292b566b9f Tests: Disable flaky css-mask-longhand test 2025-03-05 14:45:56 -05:00
Aliaksandr Kalenik
16b14273d1 Revert "LibWeb: Do not deform bitmaps partially outside the img-box"
This change broken image rendering.

This reverts commit e055927ead.
2025-03-05 19:44:49 +01:00
R-Goc
fe26c3145d AK: Add stacktrace support using the standard lib
This commit adds support for using the standard library implementation
of <stacktrace> if libbacktrace is not found. This can also be
explicitly enabled through ENABLE_STD_STACKTRACE for platforms that have
libbacktrace available.

Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-03-05 10:25:12 -07:00
Lukas Scheller
ce93088a81 LibWeb: Respect margin boxes when center-aligning flex items 2025-03-05 18:07:10 +01:00
InvalidUsernameException
495b3169e0 Tests: Mark existing workarounds consistently 2025-03-05 16:32:47 +01:00
InvalidUsernameException
e055927ead LibWeb: Do not deform bitmaps partially outside the img-box
Instead of trying to manually determine which parts of a bitmap fall
within the box of the `<img>` element, just draw the whole bitmap and
let Skia clip the draw-area to the correct rectangle.

This fixes a bug where the entire bitmap was squashed into the rectangle
of the image box instead of being clipped.

With this change, image rendering is now correct enough to import some
of the WPT tests for object-fit and object-position. To get some good
coverage I have imported all tests for the `<img>` tag. I also wanted to
import a subset of the tests for the `<object>` tag, since those are
passing as well now. Unfortunately, they are flaky for unknown reasons.
2025-03-05 16:32:47 +01:00
aplefull
389a63d6bf LibRegex: Allow duplicate named capture groups in separate alternatives 2025-03-05 14:36:09 +01:00
sideshowbarker
7df9e00650 LibWeb: Implement HTMLInputElement type=email constraint validation
This change implements HTMLInputElement type=email constraint validation
in conformance with the current spec requirements (which happens to also
produce behavior that’s interoperable with other existing engines).
2025-03-05 13:20:08 +00:00
Tommy van der Vorst
056205aa76 LibWeb/CSS: Treat 'mask' as a longhand property
Before this change, an element masked with 'mask-image: url(...)' would
show the mask, but 'mask: url(...)' would not. On e.g. dialogic.nl it
would show white boxes instead of the actual images in the top
navigation bar. We still do not support many of the other mask
properties, but with this change at least the masks show up in both
cases.
2025-03-05 12:10:02 +00:00
Lucas CHOLLET
4bf197872b LibWeb/CSS: Remove an ad-hoc simplification step in calc() parsing 2025-03-05 12:05:45 +00:00
Lucas CHOLLET
715bf0de2c LibWeb/HTML: Implement ImageData initialization closer to spec 2025-03-05 11:35:27 +00:00
Shannon Booth
569ebeb6a4 LibWeb/URLPattern: Implement IDL interface for URLPattern test and exec
There is further work needed to complete the implementation of
URL::Pattern::Pattern, but this implements the remaining URLPattern
exec and test IDL interfaces, leaving all remaining work to LibURL.
2025-03-04 16:32:09 -05:00
Shannon Booth
10b32a8dd8 LibURL/Pattern: Stub out URL::Pattern::match
This will allow us to complete the IDL interface, which will leave
remaining work to implement the URL pattern specification within
LibURL.
2025-03-04 16:32:09 -05:00
Shannon Booth
ba93e2a8a3 LibWeb/URLPattern: Implement the URLPattern constructors
The underlying URL::Pattern implementation still has to be fully
implemented, but this does complete the IDL wrapper layer of the
implementation.
2025-03-04 16:32:09 -05:00
Shannon Booth
ff07cc1a6c LibURL/Pattern: Add some scaffolding for the URLPattern constructor 2025-03-04 16:32:09 -05:00
Shannon Booth
873f7e4b3d LibURL/Pattern: Add a representation of a URL Pattern error
As the comment in this file explains the caller of LibURL APIs are
meant to assume if they see any error, that it is a TypeError since
that is all the spec throws at the moment.

A custom error type exists here so that we can include more
information in TypeError's which are thrown.
2025-03-04 16:32:09 -05:00
Shannon Booth
de89f5af6d LibURL: Remove the implicit URL constructors
All URLs are now either constucted through the URL Parser or by
default constructing a URL, and setting each of the fields of that
URL manually. This makes it much more difficult to create invalid
URLs.
2025-03-04 16:24:19 -05:00
Shannon Booth
1a47cfe3b9 Meta: Use URL basic parse for URL Fuzzer 2025-03-04 16:24:19 -05:00
Shannon Booth
3fb9c37783 UI/Qt: Do not rely on the URL implicit constructors 2025-03-04 16:24:19 -05:00
Shannon Booth
0f495421f1 UI/AppKit: Do not rely on the implicit URL constructors 2025-03-04 16:24:19 -05:00
Shannon Booth
097f7fe169 LibWeb/Loader: Explicitly parse URL generating directory response
Removing one more caller of the implicit URL constructors.
2025-03-04 16:24:19 -05:00
Shannon Booth
277aceac98 LibWeb/HTML: Parse URL track URL before creating fetch request
This is a bit weird in the spec in it passing through a string here
instead of a URL record. However, the string being used in this
case should only ever be a valid URL string if it is not the empty
string.
2025-03-04 16:24:19 -05:00
Shannon Booth
1257d0c1a8 LibWeb/HTML: Explicitly basic parse URL when following the hyperlink
Instead of relying on the implicit URL constuctor. Parsing should
never fail here as urlString before adding the suffix is already
parsed above, and the suffix should only be a valid query string.
2025-03-04 16:24:19 -05:00
Shannon Booth
2827374edc LibWebView: Handle missing URL for view source
Instead of potentially passing through an invalid URL.
2025-03-04 16:24:19 -05:00
Shannon Booth
f857c6a6e6 LibWeb/HTML: Make HTMLImageRequests currentURL a String
This is the same type as what is spec'd. We cannot use a URL record
for this member as the spec in some scenarios will set and compare
the URL string to an invalid URL value, such as the empty string.

With implicit string constructors for the URL class removed
explicitly using URL::Parser::basic_parse makes the code look
quite silly in those places.
2025-03-04 16:24:19 -05:00
Sam Atkins
9b7fb0850d LibJS+LibWebView: Treat trivia tokens as comments
Trivia is whatever whitespace and comments appear before a token.
Previously this was always given a TokenCategory of Invalid, so it
would be displayed as an error in the view-source page, with red wiggly
underlines. Instead, treat it as what it actually is: whitespace and
comments!
2025-03-04 15:54:03 -05:00
Timothy Flynn
38c1ac767d Documentation: Describe how to sniff the DevTools protocol with Firefox
For developing new LibDevTools features, it's easiest to snoop Firefox's
communication on the DevTools port to see what messages are being sent.
2025-03-04 15:42:39 -05:00
Timothy Flynn
491d1621d4 Documentation: Update the DevTools document with console.log support 2025-03-04 15:33:39 -05:00
Timothy Flynn
ffdce78b7b LibWebView+WebContent: Implement basic DevTools console support 2025-03-04 15:33:39 -05:00
Timothy Flynn
c5a22a1a97 LibDevTools+LibWebView: Implement basic support for console logging
This implements support for basic usage of console.log and friends. It
does not implement console.assert, console.trace, console.group, etc.
2025-03-04 15:33:39 -05:00
Timothy Flynn
848ac11495 LibWebView: Rename a couple of console-related callbacks for clarity
The "on_received_console_message" and "on_received_console_messages"
were indistinguishable in purpose based on their name. This renames them
to:

on_console_message_available - WebContent has output a console message
and it is available for the client to retrieve.

on_received_styled_console_messages - WebContent has replied to a
request for the available console messages.

The "styled" qualifier is used here to indicate that the messages have
been styled with CSS for display in a WebView. This is to prepare for
an upcoming patch where DevToolsConsoleClient will not stylize the
output; DevTools will want the raw JS values.
2025-03-04 15:33:39 -05:00
Timothy Flynn
14a8ffa867 WebContent: Move console handling from WebContentCC to InspectorCC
The idea originally was that the WebContentConsoleClient would perform
some amount of console handling that both InspectorConsoleClient and
DevToolsConsoleClient needed. But in implementing the DevTools console,
it's become clear that these implementations will not overlap at all. So
this patch moves the existing Inspector functionality away from
WebContentConsoleClient.
2025-03-04 15:33:39 -05:00
Timothy Flynn
1adcaf7181 AK: Fix the JsonArray constructor for accepting an iterable type
There were a couple of issues here. First, the IterableContainerOf
concept was testing if dereferencing an iterator of ContainerType<T>
returns a value of type T. However, it should return a T&.

Second, the constructor was trying to move values out of a constant
reference to the container. We now accept both lvalue and rvalue
containers.
2025-03-04 15:33:39 -05:00
sideshowbarker
38197916c3 LibWeb: Implement HTMLInputElement type=url constraint validation
This change implements HTMLInputElement type=url constraint validation
in such a way as to match the behavior in other existing engines (which
is, however, very different from what the spec currently requires).
2025-03-04 19:15:40 +00:00
Andreas Kling
6606eecce5 LibWeb: Invalidate style (and rule cache) on MediaList changes
This makes dynamic changes to a style sheet's media attribute actually
take effect immediately.
2025-03-04 19:07:40 +01:00
Aliaksandr Kalenik
80c0a16597 LibWeb: Don't invalidate style for animations in idle state 2025-03-04 18:06:46 +01:00
Aliaksandr Kalenik
b92a8553c7 LibWeb: Cancel animations when element is moved in display none subtree
We already have logic to play or cancel animations in an element's
subtree when the display property changes to or from none. However,
this was not sufficient to cover the case when an element starts/stops
being nested in display none after insertion.
2025-03-04 18:06:46 +01:00
Sam Atkins
f148af0a93 LibWeb: Move XMLSerializer into HTML directory
The DOMParsing spec is in the process of being merged into the HTML one,
gradually. The linked spec change moves XMLSerializer, but many of the
algorithms are still in the DOMParsing spec so I've left the links to
those alone.

I've done my best to update the GN build but since I'm not actually
using it, I might have done that wrong.

Corresponds to 2edb8cc7ee
2025-03-04 16:44:41 +00:00
Sam Atkins
a11848f163 IDLGenerators: Allow DOMString? reflection on non-enumerated attributes
Corresponds to ef2fba2a3b
2025-03-04 16:44:41 +00:00
Sam Atkins
d970748eed LibWeb/HTML: Assert that a finished promise has a committed-to-entry
Corresponds to 12c6ce02d8
2025-03-04 16:44:41 +00:00
Totto16
4c54fa10ed LibWeb: Improve Enum generation in IDLGenerator
Generated enums have no underlying type specifier, this adds one
It uses the smallest available, which is mostly u8
2025-03-04 16:35:04 +00:00
NotAShelf
c276cc43f0 Nix: Expose ladybird package in flake; reuse in shell
Add and expose a `ladybird` package in the Nix flake. Allows building
Ladybird only using Nix, and without relying on the dev shell. Other
users will be able to build Ladybird from source using nix3 CLI via
`nix build github:LadybirdBrowser/ladybird` or add it as a flake input
to consume the package.

We also re-use the package in the devshell, to keep dependencies in-sync
between the bleeding-edge source package, and the dev shell. This is an
upgrade to how we previously inferred dependencies to Nixpkgs package
for Ladybird, which had a chance to lack dependencies required to build
the latest commit.
2025-03-04 08:19:54 -07:00
NotAShelf
41622eaf51 Nix: Remove flake-utils from inputs
Motive: flake-utils is an unnecessary abstraction library that manages
to creep into every project under the guise of making things "easier."
There is no reason to use flake-utils here, as Nix is a powerful enough
DSL to handle system abstractions in-house without relying on more 3rd
party code, especially in a flake as small as Ladybird's.

We are not re-inventing the wheel; we are merely going back to circle
wheels.
2025-03-04 08:19:54 -07:00
Luke Wilde
e34a6c86b9 LibWeb: Introduce Content Security Policy policies and directives
These form the basis of Content Security Policy. A policy is a
collection of directives that are parsed from either the
Content-Security-Policy(-Report-Only) HTTP header, or the `<meta>`
element.

The directives are what restrict the operations can be performed in the
current global execution context. For example, "frame-ancestors: none"
tells us to prevent the page from being loaded in an embedded context,
such as `<iframe>`.

You can see it a bit like OpenBSD's pledge() functionality, but for the
web platform: https://man.openbsd.org/pledge.2
2025-03-04 14:27:19 +01:00
Rok Povsic
d17bd2c5f1 Documentation: Add instructions to uncheck 'Enable profile' for Debug 2025-03-04 06:08:43 -07:00
Rok Povsic
cff48febf0 LibWeb: Fix moving through tabs with keyboard shortcuts
Previously, despite CTRL being held, the webpage elements such as
checboxes (if existing) could 'hijact' moving to the next and previous
tab with CTRL+TAB and CTRL+SHIFT+TAB.
2025-03-04 07:37:36 -05:00
Timothy Flynn
532f156f4a LibJS: Remove some single-use Intl.DurationFormat variables
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/4c139f1
https://github.com/tc39/ecma402/commit/da498c2
https://github.com/tc39/ecma402/commit/ed5c716
2025-03-04 07:36:10 -05:00
Timothy Flynn
1e462daa9b LibJS: Simplify the Intl.DurationFormat GetDurationUnitOptions AO
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/d097048
2025-03-04 07:36:10 -05:00
Timothy Flynn
2f023c2d9c LibJS: Simplify Intl.DurationFormat.prototype.resolvedOptions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/e3d3406
2025-03-04 07:36:10 -05:00
Timothy Flynn
56a6daee4d LibJS: Standardize the spec-order of Intl.DurationFormat definitions
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/54ca35d
https://github.com/tc39/ecma402/commit/6cdcab3
https://github.com/tc39/ecma402/commit/e4cbfba
2025-03-04 07:36:10 -05:00
Timothy Flynn
aa61307392 LibJS: Re-arrange and rename a few Intl properties
This is an editorial change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/a46e37d
https://github.com/tc39/ecma402/commit/e102741
https://github.com/tc39/ecma402/commit/67a8417
https://github.com/tc39/ecma402/commit/ecb086c
2025-03-04 07:36:10 -05:00
sideshowbarker
8b0f6cb876 LibWeb: Implement “convert a string to a number” for type=time inputs 2025-03-04 12:33:09 +00:00
Totto16
678f531fe5 LibWeb: Fix IDL Generation error for enums
In the case, where IDL enums start with a character, that is an invalid
start character for C++ identifiers (e.g. a number), the C++ generaion
for enums fails. An example would be "2d" see #3788
2025-03-04 08:31:26 +00:00
Totto16
1182ee6c69 LibIDL: Report empty types with a separate error
Previously the IDL Parser Complained, that a type with the name ''
(an empty string) couldn't be found. It wasn't that easy to see the
mistake, as the not named type is printed without '' around it, so the
message seemed to miss a type. This now catches this specify error
earlier and reports it cleanly to the user. An example of this
occurring would be ''typedef A (B or //FIXME: C )
2025-03-04 08:31:26 +00:00
sideshowbarker
d14856e3c5 LibWeb: Implement “suffering from a step mismatch” constraint validation 2025-03-04 08:21:51 +00:00
Andreas Kling
12f5e9c5f8 LibWeb: Only put connected elements into document's by-name-or-id cache
This fixes an issue where disconnected elements were incorrectly
accessible as named properties on the document.
2025-03-04 00:51:50 +01:00
InvalidUsernameException
5f1a146afd LibWeb: Draw floating replaced elements more correctly
Previously floating replaced elements were drawn incorrectly and also
twice.
2025-03-03 21:49:44 +01:00
aplefull
80b2c11c81 LibJS: Implement Math.sumPrecise 2025-03-03 21:46:22 +01:00
Aliaksandr Kalenik
c769271e82 LibWeb: Don't invalidate display list in update_animated_style_if_needed
All necessary invalidations are issued while invalidating animated
style. There is no need to drop display list simply because there are
some animations that might need an update.
2025-03-03 21:45:23 +01:00
Aliaksandr Kalenik
1ce1a8f8f1 LibWeb: Reset and update animated style in a single pass
...and skip resetting animated style of finished animations.
2025-03-03 21:45:23 +01:00
Aliaksandr Kalenik
8e481f65f5 LibWeb: Don't invalidate style of finished animations
Removes lots of completely unnecessary work, especially when animated
property affects layout.
2025-03-03 21:45:23 +01:00
R-Goc
94de31ff3b AK: Remove fast_u32_xxx apis from Memory.h
This commit removes the fast_u32_fill and fast_u32_copy functions,
as they were only used in one place, and are not optimal.
2025-03-03 15:58:27 +01:00
Andreas Kling
fe2b752083 LibWeb: Don't begin link element fetch until browsing-context connected
Note that "becomes browsing-context connected" is defined as:

> When the insertion steps are invoked with it as the argument and it is
> now browsing-context connected.

This fixes an issue where WPT editing tests would clone the entire DOM
thousands of times and re-fetch all the linked CSS files once per clone.
2025-03-03 14:49:20 +01:00
Luke Wilde
6cb0f41c57 LibWeb/WebGL: Return from uniform methods if location is null
If location is null, the spec simply tells us to return and ignore the
passed in data.

Fixes #3708.
2025-03-03 08:43:33 +01:00
Timothy Flynn
b11ba4cc90 LibWeb: Clear the document's page's focused navigable upon destruction
We set the page's focused navigable upon mouse-down events from the UI.
However, we neglected to ever clear that focused navigable upon events
such as subsequent page navigations. This left the page with a stale
reference to a no-longer-active navigable. The effect was that any key
events from the UI would not be sent to the new page until either the
reference was collected by GC, or another mouse-down event occurred.

In the test added here, without this fix, the text sent to the input
element would not be received, and the change event would not fire.
2025-03-02 17:27:24 -05:00
Timothy Flynn
cf523137ad headless-browser: Do not log the inner text of crash tests
This re-implements 533c8e910a without
breaking the ability to dump layout trees.
2025-03-02 11:49:49 -05:00
Timothy Flynn
1aa009b0cf Revert "headless-browser: Do not log the inner text of crash tests"
This reverts commit 533c8e910a.

This broke the ability to dump layout trees using headless-browser.
2025-03-02 11:49:49 -05:00
aplefull
53cdb04ee8 LibJS: Fix parseFloat(-0) returning -0 instead of +0
The optimization that skips the string conversion for number values was
causing -0 to be returned as-is. This patch adds a check for this case.
2025-03-02 11:30:34 -05:00
aplefull
61744322ad LibRegex: Ensure nullable quantifiers backtrack when input remains
Makes patterns like `/(a?b??)*/` correctly match the string
2025-03-02 15:19:04 +01:00
devgianlu
40c71ff3c0 LibCrypto: Remove unused GHash class 2025-03-02 15:11:38 +01:00
devgianlu
05f3b1f361 LibCrypto+LibWeb: Refactor AES implementation with OpenSSL 2025-03-02 15:11:38 +01:00
devgianlu
75841f5920 LibCrypto: Do not print OpenSSL errors with redundant newline 2025-03-02 15:11:38 +01:00
devgianlu
80fe259dab LibCrypto: Refactor HMAC implementations with OpenSSL 2025-03-02 15:11:38 +01:00
Vaxry
c5d0af54d0 LibWeb: Don't handle scroll if no axes are accepted
In some cases, we might be hovering directly on an element
scrollable e.g. horizontally, but we are scrolling vertically.
In these cases, we need to delegate the scroll to the parent
instead of stalling the user's scroll.
2025-03-01 23:54:48 +01:00
Timothy Flynn
010463c424 LibUnicode: Specify ICU 76 in LibUnicode/CMakeLists.txt
We upgraded to ICU 76 in 6a564376fc. This
CMakeLists.txt should have been updated to match.
2025-03-01 15:09:41 -05:00
fryssen
b62a4a1a89 Documentation: Fix a typo on line 52 in Devtools.md
Typo "communcation" replaced with communication on line 52.
2025-03-01 10:31:47 -05:00
Timothy Flynn
29c8e7c203 LibJS: Disallow large dates in ToTemporalMonthDay
This is a normative change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/bd5ac12

Note: No test added here because this only affects non-ISO-8601
calendars, which we do not yet support.
2025-03-01 14:49:20 +01:00
Timothy Flynn
080d32c7d0 LibJS: Use Intl.DurationFormat for Temporal.Duration.p.toLocaleString
This is an normative change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/ffb4fb5
2025-03-01 14:49:20 +01:00
Timothy Flynn
8f51d1dd04 LibJS: Integrate Temporal.Duration into Intl.DurationFormat
This is a normative change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/2d97205
2025-03-01 14:49:20 +01:00
Timothy Flynn
f16fe66def LibJS: Migrate IsValidDuration to ECMA-262
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/03770bb

Note: We were actually already using the Temporal definition of this AO
in Intl.DurationFormat, so there's no change needed there.
2025-03-01 14:49:20 +01:00
Timothy Flynn
aa737bb654 LibJS: Migrate ToIntegerIfIntegral to ECMA-262
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/5f76109
2025-03-01 14:49:20 +01:00
Timothy Flynn
a8d6e5c3db LibJS: Migrate Temporal updates to ECMA-262 AOs to the main AO file
These are going to be included in the ECMA-262 AOs once Temporal reaches
stage 4. There's no need to keep them in the Temporal namespace. Some
upcoming Temporal editorial changes will get awkward without this patch.
2025-03-01 14:49:20 +01:00
Timothy Flynn
ea52952774 LibJS: Update Date AOs to use Temporal
Neglected to do this after the Temporal rewrite. This lets us eliminate
the duplicated GetUTCEpochNanoseconds definition in Temporal.
2025-03-01 14:49:20 +01:00
Timothy Flynn
5764eeab05 LibJS: Update spec numbers for the Intl.DurationFormat proposal
This proposal has reached stage 4 and was merged into the ECMA-402 spec.
See: https://github.com/tc39/ecma402/commit/3ff3cc7
2025-03-01 14:49:20 +01:00
Silvano Cerza
7c8d16ffca UI/AppKit: Fix template keyword misuse causing Mac build failure 2025-03-01 08:35:58 -05:00
Tim Ledbetter
19961e2b45 LibWeb: Don't halt track loading steps after sending fetch request
Previously, we would initiate a fetch request and immediately return
from the track loading steps, so the following steps would never be
executed.
2025-03-01 08:24:59 -05:00
Tim Ledbetter
6aeb3e8839 LibWeb: Fire error event if HTMLTrackElement src is empty on load
Previously, we would hang while waiting for the track to load.
2025-03-01 08:24:59 -05:00
Aliaksandr Kalenik
4d1329e0ea LibWeb: Optimize the case when invalidation set contains "whole subtree"
Instead of marking all nodes in the subtree for style recalculation,
including subtrees of subsequent siblings, we can fall back to the
default invalidation path, which is optimized to skip siblings
unaffected by sibling selectors.

Makes scrolling on https://frame.work/pl/en/about go a lot smoother.
2025-03-01 13:42:10 +01:00
stelar7
b353211700 LibWeb: Update spec comment with latest changes 2025-03-01 12:41:35 +00:00
Aliaksandr Kalenik
0f697193f0 LibWeb: Check if navigable has active window before navigating
Fixes https://github.com/LadybirdBrowser/ladybird/issues/3733
2025-02-28 23:15:35 +01:00
Ali Mohammad Pur
ea3b7efd91 LibRegex: Treat the UnicodeSets flag as Unicode
Fixes /.../v not being interpreted as a unicode pattern.
2025-02-28 14:31:45 -05:00
Luke Wilde
14ebcd4881 vcpkg: Explicitly use OpenSSL backend with curl
The generic `ssl` feature selects Secure Transport on macOS, which is a
deprecated library and support for it in curl is also deprecated and
scheduled for removal after May 2025: https://daniel.haxx.se/blog/tag/securetransport/

Secure Transport is replaced by Network Framework, but as per the blog
post above, there's no foreseeable future of curl supporting it.

With this information, we now explicitly use OpenSSL as the backend for
curl, inline with the default choice for Linux.

This gives us some key benefits:
- A maintained and current TLS library
- TLS 1.0 and 1.1 is disabled by default
- TLS 1.3 is now available
- Modern cipher suites
- Removal of TLS_EMPTY_RENEGOTIATION_INFO_SCSV extension
- Opportunity to support HTTP/3 with nghttp3 and OpenSSL's QUIC support
- More extensions, key exchanges, EC point formats, etc.
2025-02-28 14:28:29 -05:00
Sam Atkins
532c01c388 LibWeb: Implement text-decoration: spelling-error and grammar-error 2025-02-28 16:34:08 +00:00
Sam Atkins
7668f91b60 LibWeb/Editing: Allow text-decoration-foo to be a CSSKeywordValue 2025-02-28 16:34:08 +00:00
Sam Atkins
d8a73a8165 LibWeb/Painting: Paint triangle waves using Skia
This has been left unimplemented since we switched to the Skia renderer.
Now `text-decoration-style: wavy` actually paints a wavy line. :^)

We had a text-decoration test, but it only checked `solid` lines, so
I've replaced it with a modified version of the old test page from
Serenity, without the blink option, and with some thickness parameters.

I did experiment with using a `SkPath1DPathEffect` to make it repeat the
pattern for us, but I couldn't make it look good at all.
2025-02-28 16:34:08 +00:00
Luke Wilde
08246bfa8c LibCore: Don't discard subsequent results in Socket::resolve_host
Previously, we only returned the first result that looked like an IPv6
or IPv4 address.

This cropped up when attempting to connect to https://cxbyte.me/ whilst
IPv6 on the server wasn't working. Since we only returned the first
result, which happened to be the IPv6 address, we wasn't able to
connect.

Returning all results allows curl to attempt to connect to a different
IP if one of them isn't working, and potentially make a successful
connection.
2025-02-28 15:14:35 +01:00
Gingeh
93e2babc64 LibWeb: Prevent crash when loading module in worker
The import map is defined for all global objects, not just the window.
2025-02-28 14:51:20 +01:00
Sam Atkins
fc4a2eeba8 UI/AppKit: Support image cursors 2025-02-28 13:50:13 +01:00
Sam Atkins
e0b5e742de UI/AppKit: Extract gfx_bitmap_to_ns_image() code 2025-02-28 13:50:13 +01:00
Sam Atkins
bfd7ac1204 LibWeb+WebContent+UI: Support image cursors
The `cursor` property accepts a list of possible cursors, which behave
as a fallback: We use whichever cursor is the first available one. This
is a little complicated because initially, any remote images have not
loaded, so we need to use the fallback standard cursor, and then switch
to another when it loads.

So, ComputedValues stores a Vector of cursors, and then in EventHandler
we scan down that list until we find a cursor that's ready for use.

The spec defines cursors as being `<url>`, but allows for `<image>`
instead. That includes functions like `linear-gradient()`.

This commit implements image cursors in the Qt UI, but not AppKit.
2025-02-28 13:50:13 +01:00
Sam Atkins
fd2414ba35 LibWeb/Painting: Call Base::resolve_paint_properties() from children 2025-02-28 13:50:13 +01:00
Sam Atkins
d127d412c8 LibWeb/CSS: Implement CursorStyleValue
A cursor is an image, with an optional x,y hotspot.

We know that a CursorStyleValue's bitmap never needs to change size, so
we create the ShareableBitmap once and then cache it, so that we don't
have to repeatedly create an FD for it or do the work of painting.

To avoid repainting that bitmap, we cache the values that were used to
create it - what currentColor is and its length resolution context -
and only repaint when those change.
2025-02-28 13:50:13 +01:00
Sam Atkins
9cbd8a82c7 LibWeb: Only require NodeWithStyle for gradient size resolution
None of the code here actually needs a NodeWithStyleAndBoxModelMetrics,
and we'll need to be able to resolve images from inside
NodeWithStyle::apply_style().
2025-02-28 13:50:13 +01:00
Sam Atkins
a0cd6dd607 LibWeb/CSS: Support CalculatedOr::to_string() for integers and floats
IntegerOrCalculated and NumberOrCalculated's T types don't have a
to_string() method because they're i64 and double respectively, so use
String::number() for them instead.

Also rearrange this method to avoid checking the variant's contents
multiple times.
2025-02-28 13:50:13 +01:00
Sam Atkins
c77456a508 LibWeb/CSS: Clarify types of image-parsing methods
parse_image_value() always returns some kind of AbstractImageStyleValue.
2025-02-28 13:50:13 +01:00
Sam Atkins
09d2c5eb9b LibWeb/CSS: Remove unused includes from CSSStyleValue.h
A couple of these were needed transitively, so I've added them to the
relevant files.
2025-02-28 13:50:13 +01:00
Sam Atkins
1990b2fc52 LibGfx: Add ImageCursor type and Cursor variant
Besides standard cursors, we also need to support custom images. For
now, everything still uses StandardCursor.
2025-02-28 13:50:13 +01:00
Sam Atkins
6a4a60cbd5 LibWeb/CSS: Invalidate color-stop caches when source data changes
We previously only invalidated the cached color-stop data when the
painted area's size changed. However, multiple elements can use the
same gradient and be the same size, but have different parameters that
affect the gradient stop positions, for example if a stop has an em
position. This can also change for the same element over time.

The new cache instead uses these parameters as the cache key. So we
recompute the cache if lengths would resolve differently, or the area's
size is different.

The included test fails without this change.
2025-02-28 13:50:13 +01:00
Sam Atkins
3216da062a Tests: Import some CSS cursor tests 2025-02-28 13:50:13 +01:00
Timothy Flynn
f943e0114e Documentation: Update the DevTools document with console support 2025-02-28 13:08:33 +01:00
Timothy Flynn
32bc2dc7b6 LibWebView+WebContent: Begin supporting the DevTools JavaScript console
This supports evaluating the script and replying with the result. We
currently serialize JS objects to a string, but we will need to support
dynamic interaction with the objects over IPC. This does not yet support
sending console messages to DevTools.
2025-02-28 13:08:33 +01:00
Timothy Flynn
6d33b70e61 LibDevTools: Begin supporting the JavaScript console
This implements enough to execute JavaScript and reply with the result.
We do not yet support autocomplete or eager evaluation.
2025-02-28 13:08:33 +01:00
Timothy Flynn
37f07c176a LibWebView+WebContent: Create a different console client for DevTools
Our existing WebContentConsoleClient is very specific to our home-grown
Inspector. It renders console output to an HTML string. For DevTools, we
will not want this behavior; we will want to send representations of raw
JS values.

This patch makes WebContentConsoleClient a base class to handle console
input from the user, either from the Inspector or from DevTools. It then
moves the HTML rendering needed for the Inspector to a new class,
InspectorConsoleClient. And we add a DevToolsConsoleClient (currently
just stubbed) to handle needs specific to DevTools.

We choose at runtime which console client to install, based on the
--devtools command line flag.
2025-02-28 13:08:33 +01:00
Timothy Flynn
a8d3252f93 LibWebView+WebContent: Port JS console handling to String 2025-02-28 13:08:33 +01:00
Tim Ledbetter
bbcd8bd97c LibWeb: Implement FileReaderSync interface
This interface allows the user to read File or Blob objects
synchronously from inside workers.
2025-02-28 04:49:51 +00:00
Aliaksandr Kalenik
3f71907255 LibWeb: Process navigations after initial about:blank navigation is done
Otherwise finalization step of initial `about:blank` navigation might
cancel user-initiated navigations by changing ongoing navigation id.

This is implemented by marking navigable as ready to start processing
navigation in SHTQ task, because we know for sure this task cannot be
processed until finalization step of initial `about:blank` navigation
is done.
2025-02-27 23:33:05 +01:00
Tim Ledbetter
3fd1538191 LibWeb: Implement the HTMLInputElement pattern attribute 2025-02-27 21:46:08 +01:00
Sam Atkins
5651701f31 LibWeb/CSS: Remove now-redundant CalculationNode::to_string()
The main users were the `dump()` functions, which now dump their
children instead, which is more correct anyway.

The others are for serializing numeric values, so
NumericCalculationNode's to_string() is renamed to value_to_string
() and used for those for convenience.
2025-02-27 21:42:43 +01:00
Sam Atkins
5cfb8163c6 LibWeb/CSS: Sort a calculation's children during serialization
This gets us 38 more passes in our in-tree tests, plus however many more
in the rest of WPT. :^)
2025-02-27 21:42:43 +01:00
Sam Atkins
a63879330f LibWeb/CSS: Implement calc-serialization spec algorithms
This gets us 37 new subtest passes in css/css-values, and 13 passes in
our other in-tree tests (and probably some random other ones!)

As noted in comments, a few parts of this algorithm have ad-hoc
behaviour to handle some issues in the spec.
2025-02-27 21:42:43 +01:00
Sam Atkins
f97ac33cb3 LibWeb/CSS: Use NumericCalculationNode for constants
Having multiple kinds of node that hold numeric values made things more
complicated than they needed to be, and we were already converting
ConstantCalculationNodes to NumericCalculationNodes in the first
simplification pass that happens at parse-time, so they didn't exist
after that.

As noted, the spec allows for other contexts to introduce their own
numeric keywords, which might be resolved later than parse-time. We'll
need a different mechanism to support those, but
ConstantCalculationNode could not have done so anyway.
2025-02-27 21:42:43 +01:00
Sam Atkins
7b13ccabd4 Tests: Import some calc() serialization tests from WPT 2025-02-27 21:42:43 +01:00
Andreas Kling
043e96946f LibWeb: Block rendering until linked stylesheets are loaded
This commit implements the main "render blocking" behavior for link
elements, drastically reducing the amount of FOUC (flash of unstyled
content) we subject our users to.

The document will now block rendering until linked style sheets
referenced by parser-created link elements have loaded (or failed).

Note that we don't yet extend the blocking period until "critical
subresources" such as imported style sheets have been downloaded
as well.
2025-02-27 21:36:40 +01:00
Luke Wilde
5146bbe296 LibGC: Visit the edges of the cells that must survive garbage collection
Previously, we would only keep the cell that must survive alive, but
none of it's edges.

This cropped up with a GC UAF in must_survive_garbage_collection of
WebSocket in .NET's SignalR frontend implementation, where an
out-of-scope WebSocket had it's underlying EventTarget properties
garbage collected, and must_survive_garbage_collection read from the
destroyed EventTarget properties.

See: https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/clients/ts/signalr/src/WebSocketTransport.ts#L81
Found on https://www.formula1.com/ during a live session.

Co-Authored-By: Tim Flynn <trflynn89@pm.me>
2025-02-27 14:35:28 -05:00
Aliaksandr Kalenik
da5d4e9f6a LibWeb: Assign sticky insets to Layout::InlineNode
Before this change we were ignoring boxes with `display: inline` while
assigning sticky insets. This was not correct because inline boxes are
allowed to have sticky positioning.

Fixes:
https://github.com/LadybirdBrowser/ladybird/issues/3718
https://github.com/LadybirdBrowser/ladybird/issues/3507
https://github.com/LadybirdBrowser/ladybird/issues/3133
2025-02-27 19:55:46 +01:00
Aliaksandr Kalenik
4ca330adef LibWeb: Don't take rendering task from queue while running rendering
If event loop is already executing rendering task, we should not start
the next rendering task until the current one is finished.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3717
2025-02-27 17:33:32 +01:00
Aliaksandr Kalenik
b8af3fccf6 LibWeb: Wait until child navigable's SHE is ready before navigating
This change fixes a bug that can be reproduced with the following steps:
```js
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.contentWindow.location.href = ("http://localhost:8080/demo.html");
```

These steps are executed in the following order:
1. Create iframe and schedule session history traversal task that adds
   session history entry for the iframe.
2. Generate navigation id for scheduled navigation to
   `http://localhost:8080/demo.html`.
3. Execute the scheduled session history traversal task, which adds
   session history entry for the iframe.
4. Ooops, navigation to `http://localhost:8080/demo.html` is aborted
   because addings SHE for the iframe resets the navigation id.

This change fixes this by delaying all navigations until SHE for a
navigable is created.
2025-02-27 14:31:41 +01:00
Sam Atkins
718e874cc7 LibWeb/CSS: Allow whitespace inside fit-content() function 2025-02-27 13:30:36 +00:00
Gingeh
591c6b0f68 LibWeb: Update button/input activation behaviour to match spec 2025-02-27 12:42:57 +00:00
Alice Lee
ddb832afdf LibWeb: Add the new noopener-allow-popups value to OpenerPolicy 2025-02-27 11:25:26 +00:00
zoupingshi
b609d8481a LibURL+LibWeb+Tests: Remove redundant words 2025-02-27 10:35:39 +00:00
Timothy Flynn
d5be18617e LibWeb: Ensure EventHandler visits its mouse selection target
We hold a raw pointer to the mouse selection target, which is a mixin-
style class inherited only by JS::Cell classes. By not visiting this
object, we sometime had a dangling reference to it after it had been
garbage collected.
2025-02-27 09:53:13 +00:00
sideshowbarker
18a160e0e9 Docs: Prefer closely matching explicit spec AO names 2025-02-27 07:40:19 +00:00
Timothy Flynn
0d1ce48071 LibDevTools+LibWebView: Avoid dependence on LibWebView from LibDevTools
LibDevTools was implicitly including generated IPC endpoints from
LibWebView. This is not a dependency declared in the CMakeLists.txt. So
updates to the IPC file might not have caused the endpoint header to be
regenerated by the time LibDevTools is compiled, resulting in a build
error.

This patch removes that implicit dependency entirely.
2025-02-26 19:48:24 -05:00
Andreas Kling
8ab61843be LibWeb: Parse CSS fit-content(<length-percentage>) values
Before this change, we only parsed fit-content as a standalone keyword,
but CSS-SIZING-3 added it as a function as well. I don't know of
anything else in CSS that is overloaded like this, so it ends up looking
a little awkward in the implementation.

Note that a lot of code had already been prepped for fit-content values
to have an argument, we just weren't parsing it.
2025-02-27 00:44:14 +01:00
Tim Ledbetter
6fc19ec059 LibWeb: Don't close websocket if already closed in make_disappear() AO 2025-02-26 20:20:22 +01:00
Lucas CHOLLET
d8bf8a3bb9 LibGfx: Log error on invalid color profile 2025-02-26 16:14:56 +01:00
Lucas CHOLLET
f78c5548fe LibGfx: Support more CICP configurations
This adds all parameters supported by skia by default. Supporting the
other parameters would just be a matter of defining the constants, but
that's work for another time.
2025-02-26 16:14:56 +01:00
Tim Ledbetter
d114f13029 LibWeb/SVG: Respect script element type attribute
Previously, scripts would run regardless of the value of this attribute.
2025-02-26 16:08:35 +01:00
Tim Ledbetter
f4c4d3c780 LibWeb/SVG: Process script element when href attribute changes 2025-02-26 16:08:35 +01:00
Tim Ledbetter
a187d5f28f LibWeb/SVG: Process script element when its text content changes 2025-02-26 16:08:35 +01:00
sideshowbarker
db7aa68340 LibWeb: Implement checkValidity() for HTMLSelectElement
This change adds an implementation of the checkValidity() method for
HTMLSelectElement.
2025-02-26 14:07:39 +00:00
Andreas Kling
5331571fdc LibWeb: Handle interleaved table-row and table-row-group boxes
Before this change, we were always processing all row groups first,
and then all rows. This led to incorrect table layouts when rows and row
groups were encountered in anything but that order.
2025-02-26 13:50:01 +01:00
Sam Atkins
c33b465eb6 Documentation: Document how to add a new CSS property 2025-02-26 11:32:14 +00:00
Sam Atkins
05dc8f07b2 LibWeb/CSS: Remove string type from transition-property
This isn't in the spec.
2025-02-26 11:22:47 +00:00
Sam Atkins
ab4b46f990 LibWeb/CSS: Automate parsing view-transition-name 2025-02-26 11:22:47 +00:00
Sam Atkins
c729c3fcee LibWeb/CSS: Add custom-ident blacklists to Properties.json
These excluded values use a similar notation to the ranges for numeric
types: `![foo,bar,baz]` to exclude `foo`, `bar`, and `baz`.
2025-02-26 11:22:47 +00:00
Sam Atkins
c6c607884b LibWeb/CSS: Take custom-ident blacklist as a Span
Using std::initializer_list here was a bit of a hack, and makes it
awkward to pass those blacklists around.
2025-02-26 11:22:47 +00:00
Shannon Booth
9585c6c0c7 LibWeb/HTML: Implement valueAsNumber for 'date' input type 2025-02-26 11:49:35 +01:00
Luke Wilde
12a07b4fad LibWeb: Close WebSockets when document is unloaded
Previously, they would stay open for the entire WebContent lifetime,
or until the server closed the connection. This was particularly
noticeable on collaborative websites/games such as
https://jigsawpuzzles.io/, where the user using Ladybird would stick
around even after they had navigated away.
2025-02-26 11:47:32 +01:00
Luke Wilde
3224f8acb5 LibWeb/WebSockets: Implement the garbage collection rules 2025-02-26 11:47:32 +01:00
devgianlu
b8f234719d LibWeb: Support autocomplete attribute on form elements
Implement proper support for the `autocomplete` attribute in `input`,
`select` and `textarea` elements.
2025-02-26 07:01:14 +00:00
sideshowbarker
2d7080ecb3 LibWeb: Flip on checkValidity() for HTMLTextAreaElement
This is a simple change that just un-stubs our implementation of the
checkValidity() method for HTMLTextAreaElement.
2025-02-26 06:52:53 +00:00
sideshowbarker
e79319ad85 LibWeb: Implement the form-control willValidate property
This change — part of the HTML constraint-validation API (aka
“client-side form validation”) — implements the willValidate IDL/DOM
attribute/property for all form controls that support it.
2025-02-26 05:45:06 +00:00
sideshowbarker
7da5869b14 LibWeb: Implement HTMLInputElement::suffering_from_being_missing
This change implements all required “suffering from being missing”
constraints https://html.spec.whatwg.org/#suffering-from-being-missing
for HTMLInputElement.
2025-02-26 04:13:31 +00:00
sideshowbarker
7c34746571 LibWeb: Implement HTMLFormElement::checkValidity (constraint validation)
This change implements the requirements from the HTML spec at
https://html.spec.whatwg.org/#statically-validate-the-constraints
and https://html.spec.whatwg.org/#dom-form-checkvalidity — the parts of
the HTML constraint validation API (aka “client-side form validation”)
https://html.spec.whatwg.org/#the-constraint-validation-api for
HTMLFormElement itself — as well as the code for the requirements at
https://html.spec.whatwg.org/#check-validity-steps, which are the shared
requirements for the checkValidity method for individual form controls.
2025-02-26 04:13:31 +00:00
Andreas Kling
b4e47f198a LibWeb: Implement time-traveling inheritance for CSS font-size
When setting `font-family: monospace;` in CSS, we have to interpret
the keyword font sizes (small, medium, large, etc) as slightly smaller
for historical reasons. Normally the medium font size is 16px, but
for monospace it's 13px.

The way this needs to behave is extremely strange:
When encountering `font-family: monospace`, we have to go back and
replay the CSS cascade as if the medium font size had been 13px all
along. Otherwise relative values like 2em/200%/etc could have gotten
lost in the inheritance chain.

We implement this in a fairly naive way by explicitly checking for
`font-family: monospace` (note: it has to be *exactly* like that,
it can't be `font-family: monospace, Courier` or similar.)
When encountered, we simply walk the element ancestors and re-run the
cascade for the font-size property. This is clumsy and inefficient,
but it does work for the common cases.

Other browsers do more elaborate things that we should eventually care
about as well, such as user-configurable font settings, per-language
behavior, etc. For now, this is just something that allows us to handle
more WPT tests where things fall apart due to unexpected font sizes.

To learn more about the wonders of font-size, see this blog post:
https://manishearth.github.io/blog/2017/08/10/font-size-an-unexpectedly-complex-css-property/
2025-02-25 23:55:36 +01:00
Andreas Kling
263e58bbe9 LibWeb: Only calculate parent size once in compute_font_for_style_values 2025-02-25 23:55:36 +01:00
Andreas Kling
47f5da7523 LibWeb: Actually, don't align all inline content to alphabetic baseline
This essentially reverts 1b46a52cfc
and adds more tests.

The reverted change was an incorrect workaround for the real issue,
which was that we weren't creating anonymous wrapper boxes around inline
children of table-cell boxes.

Now that this has been fixed, we can go back to aligning text properly.
2025-02-25 23:55:36 +01:00
Andreas Kling
7d4d7da28a LibWeb: Wrap inline children of table-cell in anonymous block
This fixes an issue where CSS vertical-align on a table-cell box would
incorrectly apply to both the table-cell box and any inline content it
had inside.
2025-02-25 23:55:36 +01:00
Lucas CHOLLET
7197d78ea3 Tests/LibWeb: Import a PNG and CICP related test
I had to manually import the png file as the import script is unable to
find resources from within the javascript code.
2025-02-25 22:37:22 +01:00
Sam Atkins
03a058ba5e LibWeb: Update Document.write spec steps
The spec changes seem to mostly be about introducing a TrustedHTML type
which we do not yet support, so we have a couple of FIXMEs.

TrustedTypes::InjectionSink is an attempt at matching the spec, but it's
not entirely clear to me how it should work. I'm sure it'll get
revisited once we start implementing trusted types.
2025-02-25 15:19:38 +01:00
Tim Ledbetter
abe1e14812 Tests: Import some newly-passing SVG tests 2025-02-25 15:02:35 +01:00
Tim Ledbetter
96fc840b03 LibXML: Associate prefixed elements with the correct namespace
Previously, any xmlns attributes with an associated prefix were ignored.
2025-02-25 15:02:35 +01:00
Jess
88c4f71114 AK/Checked: Dont verify overflow bit in lvalue operations
Before, adding an overflow'n `Checked<T>` to another `Checked<T>` would
cause a verification faliure when instead it should propogate m_overflow
and allow the user to handle the overflow.
2025-02-25 11:20:13 +00:00
dependabot[bot]
e5966eed08 CI: Bump JamesIves/github-pages-deploy-action from 4.7.2 to 4.7.3
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.7.2 to 4.7.3.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.7.2...v4.7.3)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-25 08:42:16 +01:00
mikiubo
8a6f7b787e LibRegex: Use depth-first search in regex optimizer
use depth-first search in optimizer code bacause using breadth-first
search generate a bug. Add test example in test lib.
2025-02-25 00:09:20 +01:00
Luke Wilde
2797f9f73e LibWeb: Return actual callback object from TreeWalker::filter 2025-02-24 18:29:03 +01:00
Luke Wilde
95949ba8f2 LibWeb: Return actual callback object from NodeIterator::filter 2025-02-24 18:29:03 +01:00
Timothy Flynn
05779fbd17 Documentation: Update the DevTools document with now-supported features 2025-02-24 12:05:29 -05:00
Timothy Flynn
a76d0867d1 LibWebView: Support DOM node highlighting and inspection for DevTools 2025-02-24 12:05:29 -05:00
Timothy Flynn
afb0a0a394 LibDevTools: Support inspecting DOM node box models and computed styles 2025-02-24 12:05:29 -05:00
Timothy Flynn
3f8b65e45c LibDevTools: Stub out a layout inspector actor
The DevTools client will ask for this actor before trying to render any
box model or computed style information. We can just stub out this actor
for now.
2025-02-24 12:05:29 -05:00
Timothy Flynn
c56bf8ac93 LibDevTools: Implement a real actor for DOM nodes
The DevTools client will now send requests to the node actor, rather
than just sending messages to other actors on the node's behalf.

This exposed a slight issue in the way we assign actor IDs. Node actors
are created in the walker actor constructor, which executes before the
actor ID is incremented. So we must be sure to increment the actor ID
before invoking any actor constructors. Otherwise, the walker actor and
the first node actor have the same numeric ID.
2025-02-24 12:05:29 -05:00
Timothy Flynn
6e8d77ff7f LibDevTools: Support highlighting DOM nodes hovered in the inspector 2025-02-24 12:05:29 -05:00
Timothy Flynn
2386859e4b LibDevTools: Store highlighter actors by type
We will be asked for different highlighters throughout the DevTools
session, e.g. ViewportSizeOnResizeHighlighter and BoxModelHighlighter.
The latter will be responsible for rendering and overlay on DOM nodes
when the user hovers over a node in the inspector panel.
2025-02-24 12:05:29 -05:00
Timothy Flynn
72905c84d5 LibWeb+LibWebView+WebContent: Support both inspecting/highlighting nodes
Our own Inspector differs from most other DevTools implementations with
regard to highlighting DOM nodes as you hover elements in the inspected
DOM tree. In other implementations, as you change the hovered node, the
browser will render a box model overlay onto the page for that node. We
currently don't do this; we wait until you click the node, at which
point we both paint the overlay and inspect the node's properties.

This patch does not change that behavior, but separates the IPCs and
internal tracking of inspected nodes to support the standard DevTools
behavior. So the DOM document now stores an inspected node and a
highlighted node. The former is used for features such as "$0" in the
JavaScript console, and the latter is used for the box model overlay.
Our Inspector continues to set these to the same node.
2025-02-24 12:05:29 -05:00
Timothy Flynn
d4b7dd88b7 LibWebView: Parse inspector-related JSON strings sooner
We currently receive serialized JSON values over IPC and forward them to
them WebView callbacks, leaving it to the implementations of those
callbacks to parse the strings as JSON objects. This patch hoists that
parsing up to WebContentClient as soon as the IPC message is received.
This is to reduce the work needed for secondary implementations of these
callbacks (i.e. our Firefox DevTools server).
2025-02-24 12:05:29 -05:00
Timothy Flynn
5478f34992 LibWebView+WebContent: Transfer inspected DOM info over IPC as String
Let's avoid a whole bunch of String to ByteString to String conversions.
2025-02-24 12:05:29 -05:00
Timothy Flynn
1e841cd453 Tests: Add a test for moving an object out of a JSON value
I recently questioned whether this would work as expected:

    JsonValue value { JsonObject {} };
    auto object = move(value.as_object());

So this just adds a unit test to ensure that it does.
2025-02-24 12:05:29 -05:00
Glenn Skrzypczak
2ac16320c9 LibWeb/Canvas: Don't apply alpha to the image data
This fixes a bug that caused the `globalAlpha` to incorrectly be
applied when retrieving the image data bitmap.
2025-02-24 13:55:51 +00:00
Glenn Skrzypczak
64a234c0df LibWeb/Canvas: Correctly return globalCompositeOperation
This fixes a bug that caused the retrieved `globalCompositeOperation`
to contain quotes.
2025-02-24 13:55:51 +00:00
Jaycadox
f672c57ca7 LibWeb: Check charset UTF-16LE/BE separately for UTF-8 conversion
Previously, the charset of name "UTF-16BE/LE" would be checked against
when following standards to convert the charset to UTF-8, but in
reality, the charsets "UTF-16BE" and "UTF-16LE" should be checked
separately.

Co-authored-by: Jelle Raaijmakers <jelle@ladybird.org>
2025-02-24 14:51:41 +01:00
Timothy Flynn
436f3f99a1 Tests: Disable some particularly slow WPT rendering tests
In an effort to help with such frequent timeouts in CI.
2025-02-24 08:07:24 -05:00
Timothy Flynn
533c8e910a headless-browser: Do not log the inner text of crash tests
This information is not particularly interesting, and it can be quite
verbose (such as style-propagation-for-long-continuation-chain.html,
which would log hundreds of lines of "a"s and "b"s).
2025-02-24 08:07:24 -05:00
devgianlu
e90d2a5713 LibCrypto+LibWeb: Refactor HKDF and PBKDF2 classes with OpenSSL 2025-02-24 11:11:05 +01:00
devgianlu
6d29a32fad LibCrypto: Complete Ed25519 test 2025-02-24 11:11:05 +01:00
devgianlu
ccf467b0c7 LibCrypto: Add Ed448 test 2025-02-24 11:11:05 +01:00
devgianlu
60dcf3e023 LibCrypto: Refactor Edwards-curves implementation with OpenSSL 2025-02-24 11:11:05 +01:00
Sam Atkins
0fcd7f9aea LibWeb/DOM: Update an attribute's node document
Corresponds to b64559cc08
2025-02-23 22:36:42 +00:00
InvalidUsernameException
f7276bfab3 LibWeb: Reduced number of recompiled files for CSS property headers
This reduces the number of `.cpp` files that need to be recompiled when
one of the below header files changes as follows:

CSS/ComputedProperties.h: 1113 -> 49
CSS/ComputedValues.h: 1120 -> 209
2025-02-23 10:14:39 -05:00
InvalidUsernameException
be47f95180 LibWeb: Reduce number of recompiled files for display list headers
This reduces the number of `.cpp` files that need to be recompiled when
one of the below header files changes as follows:

Painting/Command.h: 1030 -> 61
Painting/DisplayList.h: 1030 -> 60
Painting/DisplayListRecorder.h: 557 -> 59
2025-02-23 10:14:39 -05:00
Shannon Booth
6e257897f6 LibWeb/HTML: Implement <input> element valueAsNumber for 'week'
One point to note is that I am not entirely sure what the result
of the pre-existing valueAsNumber test should be for this strange
case which does not lie exactly on a week/day boundary. Chrome
gives a negative timestamp, which seems more wrong than the result
we give, and neither gecko or WebKit appear to support the 'week'
type. So I'm considering this result acceptable for now, and this
may be something that will need more WPT tests added in the future.
2025-02-22 19:09:41 +00:00
Shannon Booth
a808cd1631 AK: Add a 'weeks_in_year' helper
A week variant of the pre-existing 'days_in_year'.
2025-02-22 19:09:41 +00:00
Shannon Booth
ad8a0e4940 AK: Introduce UnixDateTime::from_iso8601_week
This is intended to be used by the <input> element 'week' type state
and convert that to milliseconds from the Unix epoch (ignoring leap
seconds).

I am certain there is a much better way of writing this that does
not need a loop, but I am less convinced about writing that without
running into some edge case I didn't consider.
2025-02-22 19:09:41 +00:00
Shannon Booth
08331f5d62 AK: Move some time conversion constants into global scope
These can be useful outside of the scope of the function these are
used.
2025-02-22 19:09:41 +00:00
Shannon Booth
6c2ad49ed2 LibWeb/HTML: Implement <input> element valueAsNumber for 'month' 2025-02-22 19:09:41 +00:00
Shannon Booth
ea880ec8b5 Tests/LibWeb: Import <input> valueAsNumber WPT test
This speculatively includes the changes for the not-yet merged wpt#50592
merge request.
2025-02-22 19:09:41 +00:00
Andreas Kling
a706d0ebf4 LibWeb: Let getComputedStyle() show *used* values for margin/padding
We were incorrectly showing *computed* instead of *used* values for
margin and padding when inspected via getComputedStyle().
2025-02-22 20:02:16 +01:00
Andreas Kling
cdd2ccac0b LibWeb: Resolve used vertical margins on inline elements
Even though we don't actually make use of these values at the moment,
we still want them to be reflected correctly once we start exposing used
margin values soon.
2025-02-22 20:02:16 +01:00
Andreas Kling
591f06f887 LibWeb: Leave right margin along when BFC solves for width
We were incorrectly shrinking the used right margin to make it fit
within the available space, even though this was not necessary and the
margin is allowed to stretch beyond the containing block.

This is not observable yet, but will be once we start exposing used
margin values in a subsequent change.
2025-02-22 20:02:16 +01:00
Andreas Kling
a34a45bf64 LibWeb: Propagate iframe element margin attribute changes into content 2025-02-22 20:02:16 +01:00
Andreas Kling
2725142db9 LibWeb: Mark more body element attributes as presentational hints 2025-02-22 20:02:16 +01:00
Andreas Kling
a2fa3cbd69 LibWeb: Fix goofy layout tree dumps for NavigableContainerViewport
We were neglecting to emit a newline before recursing into these.
2025-02-22 20:02:16 +01:00
Luke Wilde
198cec481a LibWeb: Allow null for optional, nullable, no default value union types
For these types, it would previously only accept `undefined` for the
`null` state.

Fixes GET requests in the Turbo library always failing:
9e057f284a/src/http/fetch_request.js (L219-L220)
9e057f284a/src/http/fetch_request.js (L51-L64)

This was found on https://www.fangamer.com/.
2025-02-22 18:45:27 +01:00
Andreas Kling
16662ab230 LibWeb: Account for collapsed top margins in BFC root height calculation
By the time we're measuring the height of a BFC root, we've already
collapsed all relevant margins for the root and its descendants.
Given this, we should simply use 0 (relative to the BFC root) as the
lowest block axis coordinate (i.e Y value) for the margin edges.

This fixes a long-standing issue where BFC roots were sometimes not tall
enough to contain their children due to margins.
2025-02-22 18:41:42 +01:00
devgianlu
7eace6af66 LibTLS: Notify on_ready_to_read after handling fatal errors
The `on_ready_to_read` callback on the underlying socket will be called
for various reasons which do not always guarantee that the next read
operation will be successful. For example, the server might have sent an
alert or a TCP RST.

We handle fatal errors on the SSL connection before calling to the user
so that `can_read_without_blocking` does not falsely advertise. The same
checks should be performed there, but it is not possible due to the
function being const.
2025-02-22 18:39:58 +01:00
devgianlu
1563054a63 LibTLS: Close connection on fatal error
The OpenSSL documentation mentions that after `SSL_ERROR_SYSCALL` or
`SSL_ERROR_SSL` no further operations should be performed and
`SSL_shutdown` should not be called.

When a fatal error occurs, close the underlying socket and free the
`SSL` struct.
2025-02-22 18:39:58 +01:00
devgianlu
f74131d50a LibTLS: Pass socket address as const reference 2025-02-22 18:39:58 +01:00
devgianlu
752f5b18fd LibWebSocket: Ensure TLS connection is opened as non-blocking 2025-02-22 18:39:58 +01:00
devgianlu
85d46a71d9 LibDNS: Ensure non-blocking socket is used for TCP connections 2025-02-22 18:39:58 +01:00
devgianlu
7d692711cb LibTLS: Support opening connection as non-blocking
For OpenSSL to work properly, the socket must be non-blocking since
before the SSL connection is established.
2025-02-22 18:39:58 +01:00
devgianlu
ad6d0f6014 LibTLS: Forward non blocking errors to caller 2025-02-22 18:39:58 +01:00
rmg-x
2b32f94527 CodeGenerators: Fix clang-18 crash by specifying types explicitly
clang 18.1.8 was crashing during the build without this change.

Filed a bug report here:
https://github.com/llvm/llvm-project/issues/128359

Co-authored-by: Tim Flynn <trflynn89@pm.me>
2025-02-22 12:38:11 -05:00
Sam Atkins
ff1ef07160 LibWeb/HTML: Update HTMLButtonElement.type to match spec changes
Corresponds to part of https://github.com/whatwg/html/pull/9841 and then
https://github.com/whatwg/html/pull/11047

Adding `Auto` as a type state feels a little odd, as it's not an actual
type allowed in HTML. However, it's the default state when the value is
missing or invalid, which works out the same, as long as we never
serialize "auto", which we don't.
2025-02-22 14:59:39 +00:00
Sam Atkins
03bccb5ff1 LibWeb/HTML: Add spec comment to CRC2D::put_image_data()
Also rename imagedata -> imageData, as done here:
6a3787f6cf
2025-02-22 14:59:39 +00:00
Sam Atkins
54d41cfea3 LibWeb/HTML: Update navigation API when a same-document reload occurs
Corresponds to 3a2a05ddf8
2025-02-22 14:59:39 +00:00
Sam Atkins
d54753e9c6 LibWeb/HTML: Correct spec numbers in inner_navigate_event_firing_algo
I forgot to do this in 26b7946123, oops!
2025-02-22 14:59:39 +00:00
Sam Atkins
4374bf2202 LibWeb/HTML: Fix dialog focus restoring descendant check
Corresponds to 82135842dc
2025-02-22 14:59:39 +00:00
Psychpsyo
89f36168b7 LibWeb: Import WPT tests for view-transition-name parsing 2025-02-22 14:52:13 +00:00
Psychpsyo
c0eb072645 LibWeb: Add CSS view-transition-name 2025-02-22 14:52:13 +00:00
Psychpsyo
b833168b74 LibWeb: Add view transition UA styles 2025-02-22 14:52:13 +00:00
Tim Ledbetter
7ee33529e8 IDLGenerators: Throw TypeError if custom element is already constructed
Throwing a TypeError instead of an InvalidStateError DOMException
follows the current specification steps.
2025-02-22 05:39:23 -05:00
Tim Ledbetter
08b5cae199 LibWeb: Don't prepare script when src attribute is removed 2025-02-22 10:14:57 +01:00
Jelle Raaijmakers
63b451cb46 LibWeb: Add SVGFilterElement 2025-02-22 10:14:29 +01:00
Jelle Raaijmakers
aeef179668 LibWeb: Add SVGAnimatedEnumeration 2025-02-22 10:14:29 +01:00
Jelle Raaijmakers
1aa50ac34a LibWeb: Combine SVG tag names into a single list
We have no need to separate these tags into "SVG graphics tags" and "SVG
tags".
2025-02-22 10:14:29 +01:00
Aliaksandr Kalenik
0ab61a94d7 LibWeb: Bucket hover rules using RuleCache
Analysis of selectors on modern websites shows that the `:hover`
pseudo-class is mostly used in the subject position within relatively
simple selectors like `.a:hover`. This suggests that we could greatly
benefit from segregating them by id/class/tag name, this way reducing
number of selectors tested during hover style invalidation.

With this change, hover invalidation on Discord goes down from 70ms to
3ms on my machine. I also tested GMail and GitHub where this change
shows nice 2x-3x speedup.
2025-02-22 10:12:24 +01:00
Aliaksandr Kalenik
ff8826d582 LibWeb: Prepare RuleCache for being reusable to store hover rules
Moves code that allows to add and iterate over rules in cache into
methods defined for RuleCache.
2025-02-22 10:12:24 +01:00
Tim Ledbetter
d3c51ea05e LibWeb: Apply nowrap attribute as presentational hint 2025-02-22 09:12:08 +00:00
Tim Ledbetter
a4ee3fb1f0 LibWeb: Use type attribute to determine HTMLLinkElement mime type
Previously, the type attribute was ignored on link elements.
2025-02-21 13:52:27 +01:00
Luke Wilde
cae0ab2139 LibWeb: Make PolicyContainer GC allocated
This is required to store Content Security Policies, as their
Directives are implemented as subclasses with overridden virtual
functions. Thus, they cannot be stored as generic Directive classes, as
it'll lose the ability to call overridden functions when they are
copied.
2025-02-21 12:43:48 +00:00
Tim Ledbetter
2e27ffab6c LibWeb: Exclude inert elements from find in page queries 2025-02-21 12:41:57 +00:00
Tim Ledbetter
d410fa8381 LibWeb: Ensure inert elements are not selectable 2025-02-21 12:41:57 +00:00
Tim Ledbetter
cb405c773b LibWeb: Ensure inert elements are not visible for hit testing 2025-02-21 12:41:57 +00:00
Tim Ledbetter
8547c1a743 LibWeb: Ensure inert contenteditable elements are not editable 2025-02-21 12:41:57 +00:00
Tim Ledbetter
1e691bd26d LibWeb: Ensure inert elements are unfocusable 2025-02-21 12:41:57 +00:00
Tim Ledbetter
a9ffc6359a LibWeb: Set inertness of HTMLElement when inert attribute is changed 2025-02-21 12:41:57 +00:00
Andrew Kaster
893e9e3eac CI: Add nightly builds for the Distribution preset 2025-02-21 12:05:18 +01:00
Andrew Kaster
b7f7f58e5f LibMedia: Don't link null PlaybackStream::create eagerly
This avoids static builds putting the "no-op" implementation of
PlaybackStream::create() in the static archive before the strong
implementation later. On ELF (and probably PE/COFF too), a weak
definition in a static archive is chosen and locked-in as the
definition before a strong definition later in the archive.

Before this change, static builds would have no audio support
at all.
2025-02-21 12:05:18 +01:00
Andrew Kaster
d64566f19e CI: Add a nightly arm64 linux CI build
This requires setting VCPKG_FORCE_SYSTEM_BINARIES to 1, per vcpkg
documentation.
2025-02-21 12:05:18 +01:00
Andrew Kaster
13338a9532 CMake: Ensure build and test presets for Distribution and Debug 2025-02-21 12:05:18 +01:00
Andrew Kaster
af5f23cdda CI: Use CMake build preset directly instead of a fuzzer flag 2025-02-21 12:05:18 +01:00
Andrew Kaster
34bf42cffa CI: Use arch variable in ci.yml instead of always using 'Lagom'
This was a relic from the SerenityOS CI, where architecture meant
what architecture to build Serenity for. For just ladybird, we might
want to build ladybird for multiple architectures per OS.
2025-02-21 12:05:18 +01:00
Andreas Kling
d8f95c5050 LibWeb: Don't neglect DOM range updates on CharacterData changes
Regressed in 036327332f.

This commit moves the optimization a little later in replaceData(),
still avoiding relayout (the important part).

Recovers 480 points on WPT. :^)
2025-02-21 11:54:00 +01:00
sideshowbarker
4396dbb88e LibWeb: Sync AriaRoles.json w/ Characteristics data in current spec
This change updates the contents of the AriaRoles.json file to match the
data in the Characteristics tables in the ARIA spec — at, for example,
https://w3c.github.io/aria/#application.

Most of the changes are to match the “Supported States and Properties”
and “Inherited States and Properties” data — but some changes are to
match the “Name From” data and “Accessible Name Required” data.

This change also intentionally removes all states and properties the
Characteristics tables list as “deprecated on this role in ARIA 1.2”.
2025-02-21 09:08:56 +00:00
Glenn Skrzypczak
0750513993 LibWeb: Support reversed ordered lists
This PR adds support for the `reversed` attribute of
ordered lists.
2025-02-21 04:23:28 +00:00
Tim Ledbetter
2550b602ab LibWeb: Apply type presentational hint for HTMLLIElement 2025-02-21 01:25:30 +00:00
Tim Ledbetter
74bf7bc28e LibWeb: Apply type presentational hint for HTMLUListElement 2025-02-21 01:25:30 +00:00
Tim Ledbetter
7612f2161c LibWeb: Apply type presentational hint for HTMLOListElement 2025-02-21 01:25:30 +00:00
Andreas Kling
1b46a52cfc LibWeb: Always align inline text content to the alphabetic baseline
This fixes an issue where `vertical-align: middle` would incorrectly
shift the text away from the natural alphabetic baseline.

Fixing this makes many WPT table tests work correctly, so I'm also
importing one of them here. :^)
2025-02-21 01:16:38 +00:00
Andreas Kling
20c859519b LibWeb: Support cellpadding=0 and invalidate table cells when it changes
We were incorrectly treating cellpadding=0 as if the attribute was
missing. This commit fixes it so it behaves as `padding: 0` on cells.

When adding a test, I discovered that we were not invalidating style for
cells when their containing table's cellpadding attribute changed.
So this commit fixes that as well.
2025-02-21 01:16:38 +00:00
Timothy Flynn
fe2dff4944 AK+Everywhere: Convert JSON value serialization to String
This removes the use of StringBuilder::OutputType (which was ByteString,
and only used by the JSON classes). And it removes the StringBuilder
template parameter from the serialization methods; this was only ever
used with StringBuilder, so a template is pretty overkill here.
2025-02-20 19:27:51 -05:00
Timothy Flynn
2c03de60da AK+Everywhere: Remove now-unecessary use of ByteString with JSON types
This removes JsonObject::get_byte_string and JsonObject::to_byte_string.
2025-02-20 19:27:51 -05:00
Timothy Flynn
4791ec35bf LibDevTools+LibWebView: Port DevTools to String 2025-02-20 19:27:51 -05:00
Timothy Flynn
9879ac0893 LibWeb+WebContent+WebDriver: Port WebDriver to String 2025-02-20 19:27:51 -05:00
Timothy Flynn
bc54c0cdfb AK+Everywhere: Store JSON strings as String 2025-02-20 19:27:51 -05:00
Timothy Flynn
e591636419 AK+Everywhere: Store JSON object keys as String 2025-02-20 19:27:51 -05:00
Timothy Flynn
70eb0ba1cd AK+Everywhere: Remove the char const* JSON value constructor 2025-02-20 19:27:51 -05:00
Timothy Flynn
ee70f1327a AK: Remove unused JSON string APIs 2025-02-20 19:27:51 -05:00
Timothy Flynn
a8bc0aed4a AK: De-duplicate the definition of the JSON value variant 2025-02-20 19:27:51 -05:00
Andrew Kaster
06faa7b160 LibWebSocket+RequestServer: Resolve WebSocket hosts using our resolver 2025-02-20 15:04:50 -07:00
Andrew Kaster
eb4c565e57 LibDNS: Add missing Core::Socket include to resolver
Without this, we get incomplete type errors
2025-02-20 15:04:50 -07:00
Andrew Kaster
1809ab2743 RequestServer: Enable the new WebSocketImplCurl backend for WebSockets 2025-02-20 15:04:50 -07:00
Andrew Kaster
71942d53eb LibWebSocket+RequestServer: Add a WebSocketImpl using libcurl
This implementation can be better improved in the future by ripping
out a lot of the manual logic in LibWebSocket and rely on libcurl to
parse our message payloads. But for now, this uses the 'raw mode' of
curl websockets in connect-only mode to allow for somewhat seamless
integration into our event loop.
2025-02-20 15:04:50 -07:00
Andrew Kaster
ad985f3227 LibWebSocket: Only call send() once on WebSocketImpl
The previous implementation would call send a half-dozen times
when sending each frame of WebSocket data. This is excessive,
especially since we need to allocate a new buffer for the payload
in order to mask it anyway. Let's just allocate one buffer up front,
and send all the completed data at the end of the method
2025-02-20 15:04:50 -07:00
Andrew Kaster
c19ecf33d9 LibThreading: Clean up pthread mutex attributes and mutex itself 2025-02-20 15:04:50 -07:00
Sam Atkins
334c55c999 LibWeb/HTML: Add missing spec text/link for insert_html_element() 2025-02-20 21:55:34 +00:00
Sam Atkins
c4889f3c5c LibWeb/DOM: Stop moving is_value in create_element()
Clangd points out that 1) `set_is_value()` takes a reference so moving
isn't useful, and 2) we're reading `is_value` in step 3 after moving
it.
2025-02-20 21:55:34 +00:00
Sam Atkins
91fe0e1a1a LibWeb/HTML: Spec-ify reset_the_insertion_mode_appropriately()
It was already to-spec, with a couple of non-behavior-affecting changes,
but now it's clearer that this is the case. :^)
2025-02-20 21:55:34 +00:00
Sam Atkins
d7b4e1f2e3 LibWeb: Add missing text to find_appropriate_place_for_inserting_node() 2025-02-20 21:55:34 +00:00
Psychpsyo
3fbbe9d6a5 LibWeb: Make SelectElement arrow use text color 2025-02-20 14:06:23 -05:00
Aliaksandr Kalenik
1843a54df7 LibWeb: Skip quick selector rejection using ancestor filter if possible
If selector does not have any descendant combinators then we know for
sure it won't be filtered out by ancestor filter, which means there is
no need to check for it.

This change makes hover style invalidation go faster on Discord where
with this change we spend 4-5% in `should_reject_with_ancestor_filter()`
instead of 20%.
2025-02-20 19:48:27 +01:00
Tim Ledbetter
ea80167723 LibWeb: Apply HTMLTableSectionElement height presentational hint 2025-02-20 17:11:52 +00:00
Tim Ledbetter
3ffc7bd131 LibWeb: Apply HTMLTableElement bordercolor presentational hint 2025-02-20 17:11:52 +00:00
Andreas Kling
01c659ce9b Tests: Skip most (but not all) write/write_single HTML parser tests
These are causing too many macOS CI timeouts, so let's focus on only
running the ones that add completely new parser coverage (i.e new
variants of the tests that were already skipped.)
2025-02-20 14:32:13 +01:00
Andreas Kling
550613e526 LibWeb: Remember when HTML parser should ignore next line feed character
There's a quirk in HTML where the parser should ignore any line feed
character immediately following a `pre` or `textarea` start tag.

This was working fine when we could peek ahead in the input stream and
see the next token, but didn't work in character-at-a-time parsing with
document.write().

This commit adds the "can ignore next line feed character" as a parser
flag that is maintained across invocations, making it work in this
parsing mode as well.

20 new passes in WPT/html/syntax/parsing/ :^)
2025-02-20 14:32:13 +01:00
Andreas Kling
611833429a LibWeb: Lazily merge text nodes when invoking HTML parser incrementally
Instead of always inserting a new text node, we now continue appending
to an extisting text node if the parser's character insertion point is
a suitable text node.

This fixes an issue where multiple invocations of document.write() would
create unnecessary sequences of text nodes. Such sequences are now
merged automatically.

19 new passes in WPT/html/syntax/parsing/ :^)
2025-02-20 14:32:13 +01:00
Andreas Kling
0c0fe09e70 LibWeb: Preserve attributes in "reconstruct active formatting elements"
25 new passes in WPT/html/syntax/parsing/ :^)
2025-02-20 14:32:13 +01:00
Andreas Kling
7549f6842f LibWeb: Ensure "frameset ok" flag is disabled after parsing pre tag
2 new passes in WPT/html/syntax/parsing/ :^)
2025-02-20 14:32:13 +01:00
Andreas Kling
2e59dbd10f LibWeb: Don't process frameset token twice in "in body" insertion mode
We were neglecting to return after handling the `frameset` start tag,
which caused us to process it twice, once properly and once generically.

54 new passes in WPT/html/syntax/parsing/ :^)
2025-02-20 14:32:13 +01:00
Andreas Kling
6f7b865cd1 LibWeb: Let HTML parser handle EOF inserted by document.close()
Before this change, the explicit EOF inserted by document.close() would
instantly abort the parser. This meant that parsing algorithms that ran
as part of the parser unwinding on EOF would never actually run.

591 new passes in WPT/html/syntax/parsing/ :^)

This exposed a problem where the parser would try to insert a root
<html> element on EOF in a document where someone already inserted such
an element via direct DOM manipulation. The parser now gracefully
handles this scenario. It's covered by existing tests (which would
crash without this change.)
2025-02-20 14:32:13 +01:00
Andreas Kling
dc652aee75 LibWeb: Also run HTML parser tests in "write" and "write_single" mode
Since we don't support the "variant" meta tag stuff in WPT, I've simply
copied the test files here, and then test.js looks at the filename to
figure out which test function to use.

This incrases our coverage of the HTML parser substantially by also
invoking it via document.write() one-shot, and character-at-a-time.
2025-02-20 14:32:13 +01:00
AppleFlavored
66bdb825c8 LibWeb: Use create_entry when constructing FormData entry list
When constructing an entry list, XHR::FormDataEntry is created
manually and appended to the entry list instead of using the
spec-defined method of creating an entry.
2025-02-20 03:24:51 +00:00
Aliaksandr Kalenik
036327332f LibWeb: Early return from replace_data() if data didn't change
Allows us to avoid invalidating layout when CharacterData didn't change.

Results in visible improvement on Discord that continuously invokes
this function with the same data, which previously resulted in relayout
on every frame.
2025-02-19 22:32:09 +01:00
Aliaksandr Kalenik
0f3665e64e LibWeb: Mark should_reject_with_ancestor_filter() as inline 2025-02-19 21:52:29 +01:00
Aliaksandr Kalenik
0f8050f0bd LibWeb: Break early from rule testing in hover style invalidation
Before this change, we did the following:
1. Created a bitmap with the matching state for each rule containing
   `:hover`.
2. Changed the actively hovered element in the document.
3. Created another bitmap with the matching state for each rule
   containing `:hover`.

With this change, we iterate rule by rule and compare the matching
state. This allows us to break early once we find the first rule whose
matching state changes after the hovered element update. Additionally,
this removes the need to allocate a bitmap.
2025-02-19 21:52:29 +01:00
Aliaksandr Kalenik
e1119023e9 LibWeb: Optimize pseudo elements presence check in hover style update
Instead of using `has_pseudo_elements()` that iterates over all pseudo
elements, only check if `::before` or `::after` are present.

Before this change, `has_pseudo_elements()` was 10% of profiles on
Discord while now it's 1-2%.
2025-02-19 19:56:52 +01:00
Jess
8ed7dee0f0 LibJS: Propogate allocation errors in BigInt constructor functions 2025-02-19 09:00:59 -05:00
Jess
8fda05d8b7 LibCrypto: Introduce a falible API for SignedBigInteger::shift_left 2025-02-19 09:00:59 -05:00
Timothy Flynn
c48641c13a Documentation: Add a document describing our DevTools server 2025-02-19 08:45:51 -05:00
Timothy Flynn
dba6401260 LibWebView: Integrate the DevTools server into the WebView application
This adds a command line option to enable the DevTools server. Here, we
make the application the DevToolsDelegate to reply to requests from the
DevTools server about the state of the application.
2025-02-19 08:45:51 -05:00
Timothy Flynn
5ed91dc915 LibDevTools: Implement enough of the protocol to inspect tabs
There is a lot needed all at once to actually inspect a tab's DOM tree.
It begins with requesting a "watcher" from a TabActor. It seems there
can be many types of watchers, but here we implement the "frame" watcher
only. The watcher creates an "inspector", which in turn creates a
"walker", which is the actor ultimately responsible for serializing and
inspecting the DOM tree.

In between all that, the DevTools client will send a handful of other
informational requests. If we do not reply to these, the client will not
move forward with the walker. For example, the CSSPropertiesActor will
be asked for a list of all known CSS properties.
2025-02-19 08:45:51 -05:00
Timothy Flynn
b974e91731 LibDevTools: Implement enough of the protocol to see a tab list
Previously, we could connect to our DevTools server from Firefox, but
could not see any information on Ladybird's opened tabs. This implements
enough of the protocol to see a tab list, but we cannot yet inspect the
tabs.
2025-02-19 08:45:51 -05:00
Timothy Flynn
58bc44ba2a LibDevTools: Introduce a Firefox DevTools server library
To aid with debugging web page issues in Ladybird without needing to
implement a fully fledged inspector, we can implement the Firefox
DevTools protocol and use their DevTools. The protocol is described
here:

https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html

This commit contains just enough to connect to Ladybird from a DevTools
client.
2025-02-19 08:45:51 -05:00
Timothy Flynn
49c93d01db LibWebView: Store the tab title on the ViewImplementation
This will be needed for DevTools, to avoid the need to go into the UI
layer for this information.
2025-02-19 08:45:51 -05:00
Timothy Flynn
3904765c4f LibWebView: Add simple ID tracking to WebViews
For Firefox DevTools, we will need to track WebViews by a numerical ID.
Here, we just increment a static 64-bit counter. We can switch to using
IDAllocator if we ever have an issue with this.

This patch adds such an ID to the views and a couple of APIs to access
WebViews after creation.
2025-02-19 08:45:51 -05:00
Timothy Flynn
82206d2abb LibWeb: Move DOM::NodeType to its own file
This is to allow using these values in libraries that otherwise do not
need to depend on LibWeb.
2025-02-19 08:45:51 -05:00
Timothy Flynn
0fc1d4cd69 AK: Provide a few mutable JSON object/array accessors
We have mutable accessors on the JsonValue class already. This will be
needed for interaction with Firefox's DevTools, where we will want to
mutate the serialized DOM tree we receive from WebContent.
2025-02-19 08:45:51 -05:00
Shannon Booth
705001483a LibWeb: Make base URL of HTML::Script Optional
This is a null or a URL in the spec, which we were previously
representing through the invalid state of URL.
2025-02-19 08:01:35 -05:00
Shannon Booth
d62cf0a807 Everywhere: Remove some use of the URL constructors
These make it too easy to construct an invalid URL, which makes it
difficult to remove the valid state of URL - which this API relies
on.
2025-02-19 08:01:35 -05:00
Shannon Booth
2823ac92d0 RequestServer: Do not check for invalid URL starting a request
Now that LibIPC ensures that an invalid URL is not passed through,
we do not need to check the validity of the URL here.
2025-02-19 08:01:35 -05:00
Shannon Booth
25df98875d LibIPC: Ensure only valid URLs are passed over IPC
Invalid URLs should be signified by a wrapper class, such as an
Optional<URL::URL> in the IPC file. I do not believe that we have
anything which currently relies on passing through an invalid URL.
2025-02-19 08:01:35 -05:00
Shannon Booth
0b8bcdcbd3 LibWeb: Remove some useless URL validity checks
It is not possible for a URL here to have a value and be invalid.
2025-02-19 08:01:35 -05:00
Shannon Booth
dc2b0e17bf LibWeb/ServiceWorker: Use has_value for checking for invalid URL
This is the correct API to call here.
2025-02-19 08:01:35 -05:00
Shannon Booth
c86b5068d0 xml: Remove validity check on URL created with file scheme
It is not possible for this to return an invalid URL.
2025-02-19 08:01:35 -05:00
Shannon Booth
2c8dab36f3 LibWeb: Port EnvironmentSettings URL Parsing to return Optional<URL> 2025-02-19 08:01:35 -05:00
Jelle Raaijmakers
5f5d18d719 LibWeb: Do not crash when inserting block elements into inline SVGBoxes
Fixes #3395.
2025-02-19 13:49:24 +01:00
Jelle Raaijmakers
0c58dad7a6 LibWeb: Factor out conditions for creation of inline continuation
Having one big `if` to determine whether or not we should restructure an
inline layout node became a bit unwieldy. This extracts the logic into a
separate method.
2025-02-19 13:49:24 +01:00
Jelle Raaijmakers
c0109039cb LibWeb: Do not consider <foreignObject> for inline continuation
We used to have an exception for this element that erroneously got
removed in 336684bc5c.

Fixes #3453.
2025-02-19 13:49:24 +01:00
Piotr
c9edb6ffc4 LibWeb: Support for Content-Language HTTP header 2025-02-19 10:53:31 +00:00
Andrew Kaster
dda1573746 Devcontainer: Set VCPKG_FORCE_SYSTEM_BINARIES when building cache
vcpkg requires this flag to be set when building on non-x86 Linux,
as they don't ship enough cached tools for those platforms.

Put another way, we must allow system-installed versions of tools
such as CMake, Ninja, and pkg-config into the vcpkg build process
on these platforms.
2025-02-18 15:33:51 -07:00
Jelle Raaijmakers
de7ca7b157 LibWeb: Retain display: contents in ancestor stack for continuations
When restructuring inline nodes because of a block element insertion
during the layout tree build, we might end up with a `display: contents`
element in the ancestor stack that is not part of the actual layout
tree, since it's never actually used as a parent for any node. Because
we were only rewinding the ancestor stack with actual new layout nodes,
it became corrupted and layout nodes were added to the wrong parent.

This new logic leaves the ancestor stack intact, only replacing layout
nodes whenever a new one is created.

Fixes the sidebar on https://reddit.com.
Fixes #3590.
2025-02-18 23:31:49 +01:00
Tim Ledbetter
dd8cca180f LibWeb: Remove unintentional recursion in ValidityState::valid 2025-02-18 21:58:35 +01:00
Andrew Kaster
8e3798b25e LibWeb: Convert ConnectionTimingInfo to a standard layout struct
There's nothing about this type that requires it to be GC allocated
2025-02-18 11:26:34 -07:00
Andrew Kaster
47716a4e11 LibWeb: Explicitly capture resource in closures in load_resource
A hygine patch to not use a generic = capture, and remove some
unnecessary const-casts
2025-02-18 11:26:34 -07:00
Andrew Kaster
8760825bb4 LibWeb: Don't store Page on ResourceLoader
We only need a Page for file:// urls. At some point we probably
needed it for other kinds of requests, but the current functionality
doesn't need to store the Page pointer on the ResourceLoader.
2025-02-18 11:26:34 -07:00
Andrew Kaster
a869a1c056 LibWeb: Establish WebSocket connections in parallel 2025-02-18 11:26:34 -07:00
Psychpsyo
aa243000f3 LibWeb: Implement TimeRanges and HTMLMediaElement.seekable() 2025-02-18 10:45:32 -07:00
Psychpsyo
3952ff4786 LibWeb: Add a stub for HTMLMediaElement.played() 2025-02-18 10:45:32 -07:00
Psychpsyo
0206697d36 LibWeb: Implement MediaCapabilities.decodingInfo() 2025-02-18 10:18:40 -07:00
Psychpsyo
3b577e6135 Meta: Improve IDL generator for dictionary members
This makes it so that the IDL generator no longer assumed that
dictionary members with a default value are optional, since they
will always, at least, have the default value.
2025-02-18 10:18:40 -07:00
Psychpsyo
96bb250a4a LibWeb: Import setCustomValidity related tests 2025-02-18 10:17:06 -07:00
Psychpsyo
a8004a77bb LibWeb: Implement setCustomValidity IDL attribute 2025-02-18 10:17:06 -07:00
devgianlu
0926720c2a LibDNS: Add basic DNS::Resolver tests 2025-02-18 15:46:44 +01:00
devgianlu
42a18a4a91 RequestServer: Use default certificate for DNS over TLS 2025-02-18 15:46:44 +01:00
devgianlu
65966020d1 LibTLS: Forward can_read_without_blocking to underlying socket 2025-02-18 15:46:44 +01:00
Tim Ledbetter
0e470d5cdf LibWeb: Apply presentational hints for the HTMLHRElement align attribute 2025-02-18 12:06:44 +01:00
Tim Ledbetter
c217057cfd LibWeb: Apply presentational hints for the HTMLHRElement color attribute 2025-02-18 12:06:44 +01:00
Psychpsyo
83c4e22247 LibWeb: Implement validity IDL attribute 2025-02-18 06:37:11 +00:00
Aliaksandr Kalenik
184ae687c5 LibWeb+WebContent: Remove unused code in BrowsingContext 2025-02-17 19:11:14 -05:00
Shannon Booth
cf7b775709 LibWeb/URLPattern: Implement the URLPattern IDL getters
These simply return the compiled URLPattern pattern strings for
each component, and whether any of the components contained any
regexp groups.
2025-02-17 19:10:39 -05:00
Shannon Booth
f3662c6f88 LibURL/Pattern: Add a representation of a URL Pattern
This is the core object behind a URL pattern which when constructed
can be used for matching the pattern against URLs.

However, the implementation here is missing key functions such as
the constructor and the 'test'/'exec' functions as that relies on
a significant amount of supporting URLPattern infrastructure such
as two different parsers and a tokenizer.

However, this is enough for us to implement some more of the IDL
wrapper layer of this specification.
2025-02-17 19:10:39 -05:00
Shannon Booth
5521836929 LibURL/Pattern: Add a representation of a URL Pattern 'component'
A URL pattern consists of components such as the 'port', 'password'
'hostname', etc. A component is compiled from the input to the
URLPattern constructor and is what is used for matching against
URLs to produce a match result.

This is also where the regex dependency is introduced into LibURL
to support the URLPattern implementation.
2025-02-17 19:10:39 -05:00
Aliaksandr Kalenik
93253e993b LibWeb: Fix invalidations calculation for values with relative units
...in inherited style update. Instead of comparing old absolutized value
with new non-absolutized value, we should wait until
`absolutize_values()` and then compare old and new values, when both are
absolutized.

Improves performance on pages with GitHub action logs where previously
we had to invalidate layout after hover style recalculation, because
there was `margin-left: 1rem`.
2025-02-18 00:24:45 +01:00
Aliaksandr Kalenik
9dd59e0673 LibWeb: Early return when invalidations=none in animation style update
This allows to skip a bunch of unnecessary work performed by
`apply_style()`.
2025-02-18 00:24:45 +01:00
Aliaksandr Kalenik
1e07227e98 LibWeb: Early return when invalidations=none in inherited style update
This allows to skip a bunch of unnecessary work performed by
`apply_style()`.
2025-02-18 00:24:45 +01:00
Aliaksandr Kalenik
e5b4fe2c65 LibWeb: Fix wrong invalidations calculation in inherited style update
We were incorrectly comparing new value against itself instead of the
old value to determine required set of invalidations.
2025-02-18 00:24:45 +01:00
devgianlu
ba607e2127 LibCrypto: Add SECP521r1 test 2025-02-18 00:02:26 +01:00
devgianlu
f630ca7cd0 LibCrypto: Rename and remove unused methods from SECPxxxr1 class 2025-02-18 00:02:26 +01:00
devgianlu
048d6b8012 LibCrypto: Remove unused constructors from RSA class 2025-02-18 00:02:26 +01:00
devgianlu
3431b3235c LibCrypto: Prevent exporting invalid DER RSAPrivateKey 2025-02-18 00:02:26 +01:00
devgianlu
7180c5f13b LibCrypto: Remove unused EllipticCurve abstract class
This was required only to support our custom TLS implementation, but
does not serve any purpose other than forcing improper APIs.
2025-02-18 00:02:26 +01:00
devgianlu
8ae01f81c9 LibCrypto: Remove unused MGF class 2025-02-18 00:02:26 +01:00
devgianlu
510aa223c2 LibCrypto: Remove unused ChaCha20 class 2025-02-18 00:02:26 +01:00
devgianlu
7fb15ef936 LibCrypto: Remove unused Poly1305 class 2025-02-18 00:02:26 +01:00
devgianlu
ce3e79a402 LibCrypto: Remove unused ChaCha20Poly1305 class 2025-02-18 00:02:26 +01:00
devgianlu
bc0bb0d535 LibCrypto: Remove unused Certificate class 2025-02-18 00:02:26 +01:00
devgianlu
24d3da64e5 LibWebSocket: Support specifying root certificate path 2025-02-17 19:52:43 +01:00
devgianlu
b8f609099a LibTLS: Remove unused DefaultRootCACertificates
The certificates are set inside `DefaultRootCACertificates` in some
places, but no one reads them.
2025-02-17 19:52:43 +01:00
devgianlu
7a38a3e994 LibTLS: Replace TLSv12 implementation with OpenSSL 2025-02-17 19:52:43 +01:00
devgianlu
d6e9d2cdbb LibCore: Expose TCPSocket file descriptor 2025-02-17 19:52:43 +01:00
devgianlu
b6ec31b590 LibCrypto: Move OPENSSL_TRY helper function outside namespace
This allows using `OPENSSL_TRY` and `OPENSSL_TRY_PTR` outside of the
`Crypto` namespace.
2025-02-17 19:52:43 +01:00
devgianlu
53dd99098c LibTLS: Move DefaultRootCACertificates to own file 2025-02-17 19:52:43 +01:00
devgianlu
6889fa9695 LibWeb: Add simple in-tree WebSocket test 2025-02-17 19:52:43 +01:00
5744 changed files with 252606 additions and 78567 deletions

View File

@ -19,6 +19,7 @@ RemoveSemicolon: true
RequiresClausePosition: WithFollowing
RequiresExpressionIndentation: OuterScope
SpaceAfterTemplateKeyword: false
WrapNamespaceBodyWithEmptyLines: Always
---
Language: ObjC

View File

@ -6,7 +6,7 @@
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-contrib/features/pre-commit:2": {},
"./features/ladybird": {
"llvm_version": 19
"llvm_version": 20
},
"./features/vcpkg-cache": {
"release_triplet": true,

View File

@ -18,12 +18,12 @@
"llvm_version": {
"type": "string",
"proposals": [
17,
18,
19,
20,
"trunk"
],
"default": 19,
"default": 20,
"description": "Select LLVM compiler version to use"
}
}

View File

@ -6,5 +6,5 @@ dnf install -y git gh
# Ladybird dev dependencies
dnf install -y autoconf-archive automake ccache cmake curl google-noto-sans-mono-fonts liberation-sans-fonts libglvnd-devel \
nasm ninja-build perl-FindBin perl-IPC-Cmd perl-lib qt6-qtbase-devel qt6-qtmultimedia-devel qt6-qttools-devel \
nasm ninja-build patchelf perl-FindBin perl-IPC-Cmd perl-lib qt6-qtbase-devel qt6-qtmultimedia-devel qt6-qttools-devel \
qt6-qtwayland-devel tar unzip zip zlib-ng-compat-static

View File

@ -5,6 +5,14 @@ set -e
# FIXME: Add some options to make this more flexible and usable by other projects
# FIXME: Find a way to do this without cloning ladybird
case "$(uname -m)" in
x86_64|x64)
;;
*)
export VCPKG_FORCE_SYSTEM_BINARIES=1
;;
esac
cd /tmp
CACHE_DIR=/usr/local/share/vcpkg-binary-cache

View File

@ -6,7 +6,7 @@
"context": ".",
"dockerfile": "Dockerfile",
"args": {
"VERSION": "${localEnv:VERSION:41}"
"VERSION": "${localEnv:VERSION:42}"
}
},

1
.github/FUNDING.yml vendored
View File

@ -1,2 +1,3 @@
custom: https://donorbox.org/ladybird
open_collective: ladybird
polar: LadybirdBrowser

View File

@ -3,6 +3,9 @@ description: 'Restores caches of downloaded files and build artifacts.'
author: 'Andrew Kaster <akaster@serenityos.org>'
inputs:
runner_label:
description: 'Name of runner instance'
required: true
os:
description: 'Operating System to restore caches for'
required: true
@ -31,11 +34,18 @@ inputs:
description: 'Path to the download cache directory'
required: false
default: 'caches'
vcpkg_cache_path:
description: 'Path to vcpkg binary cache'
required: false
default: ''
outputs:
ccache_primary_key:
description: 'Primary ccache key'
value: ${{ steps.ccache.outputs.cache-primary-key }}
value: ${{ steps.cache-outputs.outputs.ccache_primary_key }}
vcpkg_cache_primary_key:
description: 'Primary vcpkg binary cache key'
value: ${{ steps.cache-outputs.outputs.vcpkg_cache_primary_key }}
runs:
using: "composite"
@ -46,15 +56,27 @@ runs:
run: |
echo "timestamp=$(date -u "+%Y%m%d%H%M_%S")" >> "$GITHUB_OUTPUT"
- name: 'Compiler Cache'
uses: actions/cache/restore@v4
id: 'ccache'
if: ${{ inputs.ccache_path != '' }}
- name: 'Compiler Cache (blacksmith)'
uses: useblacksmith/cache/restore@v5
id: 'ccache-blacksmith'
if: ${{ inputs.ccache_path != '' && startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.ccache_path }}
key: '"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}" | ${{ steps.date-stamp.outputs.timestamp }}'
restore-keys: |
"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}"
path: ${{ inputs.ccache_path }}
key: '"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}" | ${{ steps.date-stamp.outputs.timestamp }}'
restore-keys: |
ccache | ${{ inputs.os }} | ${{ inputs.arch }} | ${{ inputs.toolchain }} | ${{ inputs.cache_key_extra }} | ${{ inputs.ccache_version }}
"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}"
- name: 'Compiler Cache (GitHub runner)'
uses: actions/cache/restore@v4
id: 'ccache-gh'
if: ${{ inputs.ccache_path != '' && !startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.ccache_path }}
key: '"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}" | ${{ steps.date-stamp.outputs.timestamp }}'
restore-keys: |
ccache | ${{ inputs.os }} | ${{ inputs.arch }} | ${{ inputs.toolchain }} | ${{ inputs.cache_key_extra }} | ${{ inputs.ccache_version }}
"ccache" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}"
- name: 'Configure Compiler Cache'
if: ${{ inputs.ccache_path != '' }}
@ -68,9 +90,38 @@ runs:
CCACHE_DIR=${{ inputs.ccache_path }} ccache -s
CCACHE_DIR=${{ inputs.ccache_path }} ccache -z
- name: Export vcpkg GitHub Actions cache environment variables
uses: actions/github-script@v7
- name: 'Restore vcpkg cache (blacksmith)'
uses: useblacksmith/cache/restore@v5
if: ${{ inputs.vcpkg_cache_path != '' && startsWith(inputs.runner_label, 'blacksmith') }}
id: 'vcpkg-blacksmith'
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
path: ${{ inputs.vcpkg_cache_path }}
key: '"vcpkg" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}" | ${{ steps.date-stamp.outputs.timestamp }}'
restore-keys: |
vcpkg | ${{ inputs.os }} | ${{ inputs.arch }} | ${{ inputs.toolchain }} | ${{ inputs.cache_key_extra }} | ${{ inputs.ccache_version }}
"vcpkg" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}"
- name: 'Restore vcpkg cache (GitHub runner)'
uses: actions/cache/restore@v4
if: ${{ inputs.ccache_path != '' && !startsWith(inputs.runner_label, 'blacksmith') }}
id: 'vcpkg-gh'
with:
path: ${{ inputs.vcpkg_cache_path }}
key: '"vcpkg" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}" | ${{ steps.date-stamp.outputs.timestamp }}'
restore-keys: |
vcpkg | ${{ inputs.os }} | ${{ inputs.arch }} | ${{ inputs.toolchain }} | ${{ inputs.cache_key_extra }} | ${{ inputs.ccache_version }}
"vcpkg" | "${{ inputs.os }}" | "${{ inputs.arch }}" | "${{ inputs.toolchain }}" | "${{ inputs.cache_key_extra }}" | "${{ inputs.ccache_version }}"
# FIXME: When all runners are using the useblacksmith/cache action and this step is removed, we should also be able
# to remove the quoteless cache restore keys in the cache actions above.
- name: 'Cache Outputs'
id: 'cache-outputs'
shell: bash
run: |
if ${{ startsWith(inputs.runner_label, 'blacksmith') }} ; then
echo "ccache_primary_key=${{ steps.ccache-blacksmith.outputs.cache-primary-key }}" >> "$GITHUB_OUTPUT"
echo "vcpkg_cache_primary_key=${{ steps.vcpkg-blacksmith.outputs.cache-primary-key }}" >> "$GITHUB_OUTPUT"
else
echo "ccache_primary_key=${{ steps.ccache-gh.outputs.cache-primary-key }}" >> "$GITHUB_OUTPUT"
echo "vcpkg_cache_primary_key=${{ steps.vcpkg-gh.outputs.cache-primary-key }}" >> "$GITHUB_OUTPUT"
fi

View File

@ -3,6 +3,9 @@ description: 'Saves caches of build artifacts.'
author: 'Andrew Kaster <akaster@serenityos.org>'
inputs:
runner_label:
description: 'Name of runner instance'
required: true
arch:
description: 'Target Architecture to restore caches for'
required: false
@ -15,6 +18,14 @@ inputs:
description: 'Primary ccache key'
required: false
default: ''
vcpkg_cache_path:
description: 'Path to the vcpkg binary cache directory'
required: false
default: ''
vcpkg_cache_primary_key:
description: 'Primary vcpkg binary cache key'
required: false
default: ''
runs:
using: "composite"
@ -25,14 +36,36 @@ runs:
run: |
CCACHE_DIR=${{ inputs.ccache_path }} ccache --evict-older-than=1d
- name: 'Compiler Cache'
- name: 'Compiler Cache (blacksmith)'
uses: useblacksmith/cache/save@v5
if: ${{ inputs.ccache_path != '' && startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.ccache_path }}
key: ${{ inputs.ccache_primary_key }}
- name: 'Compiler Cache (GitHub runner)'
uses: actions/cache/save@v4
if: ${{ inputs.ccache_path != '' }}
if: ${{ inputs.ccache_path != '' && !startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.ccache_path }}
key: ${{ inputs.ccache_primary_key }}
- name: 'Cache Stats'
shell: bash
if: ${{ inputs.ccache_path != '' }}
run: |
CCACHE_DIR=${{ inputs.ccache_path }} ccache -s
- name: 'vcpkg binary cache (blacksmith)'
uses: useblacksmith/cache/save@v5
if: ${{ inputs.vcpkg_cache_path != '' && startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.vcpkg_cache_path }}
key: ${{ inputs.vcpkg_cache_primary_key }}
- name: 'vcpkg binary cache (GitHub runner)'
uses: actions/cache/save@v4
if: ${{ inputs.vcpkg_cache_path != '' && !startsWith(inputs.runner_label, 'blacksmith') }}
with:
path: ${{ inputs.vcpkg_cache_path }}
key: ${{ inputs.vcpkg_cache_primary_key }}

View File

@ -8,8 +8,12 @@ inputs:
default: 'Linux'
arch:
description: 'Target Architecture to set up'
required: false
required: true
default: 'x86_64'
toolchain:
description: 'Toolchain to set up'
required: true
default: 'Clang'
runs:
using: "composite"
steps:
@ -27,20 +31,31 @@ runs:
run: |
set -e
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
if [ ! -f /etc/apt/sources.list.d/llvm.list ]; then
curl -f -o /usr/share/keyrings/llvm-snapshot.gpg.key https://apt.llvm.org/llvm-snapshot.gpg.key
echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg.key] http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main" | sudo tee -a /etc/apt/sources.list.d/llvm.list
fi
sudo apt-get update -y
sudo apt-get install -y autoconf autoconf-archive automake build-essential ccache clang-19 clang++-19 cmake curl fonts-liberation2 \
gcc-13 g++-13 libegl1-mesa-dev libgl1-mesa-dev libpulse-dev libssl-dev \
libstdc++-13-dev lld-19 nasm ninja-build qt6-base-dev qt6-tools-dev-tools tar unzip zip
sudo apt-get install -y autoconf autoconf-archive automake build-essential ccache cmake curl fonts-liberation2 \
gcc-14 g++-14 libcurl4-openssl-dev libegl1-mesa-dev libgl1-mesa-dev libpulse-dev libssl-dev \
libstdc++-14-dev lld-20 llvm-20 nasm ninja-build qt6-base-dev qt6-tools-dev-tools tar unzip zip
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 100
if ${{ inputs.toolchain == 'Clang' }} ; then
sudo apt-get install -y clang-20 clang++-20 clang-tools-20
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 100
fi
wget https://github.com/WebAssembly/wabt/releases/download/1.0.35/wabt-1.0.35-ubuntu-20.04.tar.gz
sudo update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-20 100
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100
# FIXME: https://github.com/WebAssembly/wabt/issues/2533
# wabt doesn't have binary releases for arm64 Linux
curl -f -L -o wabt-1.0.35-ubuntu-20.04.tar.gz https://github.com/WebAssembly/wabt/releases/download/1.0.35/wabt-1.0.35-ubuntu-20.04.tar.gz
tar -xzf ./wabt-1.0.35-ubuntu-20.04.tar.gz
rm ./wabt-1.0.35-ubuntu-20.04.tar.gz
echo "${{ github.workspace }}/wabt-1.0.35/bin" >> $GITHUB_PATH
@ -49,7 +64,51 @@ runs:
if: ${{ inputs.os == 'macOS' || inputs.os == 'Android' }}
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 16.1
xcode-version: 16.3
- name: 'Install Swift toolchain'
if: ${{ inputs.toolchain == 'Swift' }}
shell: bash
run: |
set -e
export SWIFTLY_HOME_DIR=${{ github.workspace }}/.swiftly/share
export SWIFTLY_BIN_DIR=${{ github.workspace }}/.swiftly/bin
echo "$SWIFTLY_BIN_DIR" >> $GITHUB_PATH
echo "SWIFTLY_HOME_DIR=$SWIFTLY_HOME_DIR" >> $GITHUB_ENV
echo "SWIFTLY_BIN_DIR=$SWIFTLY_BIN_DIR" >> $GITHUB_ENV
export PATH=$SWIFTLY_BIN_DIR:$PATH
mkdir -p $SWIFTLY_HOME_DIR
mkdir -p $SWIFTLY_BIN_DIR
if ${{ inputs.os == 'Linux' }} ; then
curl -O https://download.swift.org/swiftly/linux/swiftly-${{ inputs.arch }}.tar.gz
file swiftly-${{ inputs.arch }}.tar.gz
tar -xzf swiftly-${{ inputs.arch }}.tar.gz -C $SWIFTLY_BIN_DIR
rm swiftly-${{ inputs.arch }}.tar.gz
else
# FIXME: https://github.com/swiftlang/swiftly/issues/271
# Why does this drop files in $HOME? That's not very CI-friendly
curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg
installer -pkg swiftly.pkg -target CurrentUserHomeDirectory
cp ~/.swiftly/bin/swiftly $SWIFTLY_BIN_DIR
rm swiftly.pkg
fi
swiftly init \
--no-modify-profile \
--quiet-shell-followup \
--assume-yes \
--skip-install \
--verbose
echo "swiftly version: $(swiftly --version)" >&2
swiftly install --use main-snapshot-2025-05-26
swiftly list
- name: 'Install Dependencies'
if: ${{ inputs.os == 'macOS' || inputs.os == 'Android' }}
@ -57,8 +116,15 @@ runs:
run: |
set -e
brew update
brew install autoconf autoconf-archive automake bash ccache coreutils llvm@19 nasm ninja qt unzip wabt
brew install autoconf autoconf-archive automake bash ccache coreutils llvm@20 nasm ninja pkg-config qt unzip wabt
- name: 'Set required environment variables'
if: ${{ inputs.os == 'Linux' && inputs.arch == 'arm64' }}
uses: actions/github-script@v7
with:
script: |
core.exportVariable('VCPKG_FORCE_SYSTEM_BINARIES', '1')
- name: 'Install vcpkg'
shell: bash
run: ./Toolchain/BuildVcpkg.sh
run: ./Toolchain/BuildVcpkg.py

View File

@ -15,34 +15,39 @@ jobs:
fail-fast: false
matrix:
os_name: ['Linux']
os: [ubuntu-24.04]
fuzzer: ['NO_FUZZ']
arch: ['x86_64']
build_preset: ['Sanitizer_CI']
toolchain: ['GNU']
clang_plugins: [false]
runner: ['blacksmith-16vcpu-ubuntu-2404']
include:
- os_name: 'Linux'
os: ubuntu-24.04
fuzzer: 'NO_FUZZ'
arch: 'x86_64'
build_preset: 'Sanitizer_CI'
toolchain: 'Clang'
clang_plugins: true
runner: 'blacksmith-16vcpu-ubuntu-2404'
- os_name: 'macOS'
os: macos-15
fuzzer: 'NO_FUZZ'
arch: 'arm64'
build_preset: 'Sanitizer_CI'
toolchain: 'Clang'
clang_plugins: false
runner: 'macos-15'
- os_name: 'Linux'
os: ubuntu-24.04
fuzzer: 'FUZZ'
arch: 'x86_64'
build_preset: 'Fuzzers_CI'
toolchain: 'Clang'
clang_plugins: false
runner: 'blacksmith-16vcpu-ubuntu-2404'
uses: ./.github/workflows/lagom-template.yml
with:
toolchain: ${{ matrix.toolchain }}
os_name: ${{ matrix.os_name }}
os: ${{ matrix.os }}
fuzzer: ${{ matrix.fuzzer }}
runner: ${{ matrix.runner }}
arch: ${{ matrix.arch }}
build_preset: ${{ matrix.build_preset }}
clang_plugins: ${{ matrix.clang_plugins }}

View File

@ -8,26 +8,24 @@ env:
LADYBIRD_SOURCE_DIR: ${{ github.workspace }}
CCACHE_DIR: ${{ github.workspace }}/.ccache
VCPKG_ROOT: ${{ github.workspace }}/Build/vcpkg
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
jobs:
build-and-package:
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.runner }}
if: github.repository == 'LadybirdBrowser/ladybird'
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04]
package_type: [Linux-x86_64]
os_name: [Linux]
include:
- os: macos-14
package_type: macOS-universal2
os_name: macOS
os_name: ['Linux']
arch: ['x86_64']
package_type: ['Linux-x86_64']
runner: ['blacksmith-8vcpu-ubuntu-2404']
concurrency:
group: ${{ github.workflow }}-${{ matrix.os_name }}
cancel-in-progress: true
include:
- os_name: 'macOS'
arch: 'arm64'
package_type: 'macOS-arm64'
runner: 'macos-15'
steps:
- name: Checkout LadybirdBrowser/ladybird
@ -37,23 +35,25 @@ jobs:
uses: ./.github/actions/setup
with:
os: ${{ matrix.os_name }}
arch: 'Lagom'
arch: ${{ matrix.arch }}
- name: Restore Caches
uses: ./.github/actions/cache-restore
id: 'cache-restore'
with:
runner_label: ${{ matrix.runner }}
os: ${{ matrix.os_name }}
arch: 'Lagom'
arch: ${{ matrix.arch }}
cache_key_extra: 'LibJS Artifacts'
ccache_path: ${{ env.CCACHE_DIR }}
download_cache_path: ${{ github.workspace }}/Build/caches
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
- name: Create build directory Ubuntu
run: |
cmake --preset Distribution_CI \
-DCMAKE_C_COMPILER=clang-19 \
-DCMAKE_CXX_COMPILER=clang++-19 \
-DCMAKE_C_COMPILER=clang-20 \
-DCMAKE_CXX_COMPILER=clang++-20 \
-DENABLE_GUI_TARGETS=OFF
if: ${{ matrix.os_name == 'Linux' }}
@ -77,9 +77,12 @@ jobs:
- name: Save Caches
uses: ./.github/actions/cache-save
with:
runner_label: ${{ matrix.runner }}
arch: 'Lagom'
ccache_path: ${{ env.CCACHE_DIR }}
ccache_primary_key: ${{ steps.cache-restore.outputs.ccache_primary_key }}
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
vcpkg_cache_primary_key: ${{ steps.cache-restore.outputs.vcpkg_cache_primary_key }}
- name: Upload js package
uses: actions/upload-artifact@v4

92
.github/workflows/js-benchmarks.yml vendored Normal file
View File

@ -0,0 +1,92 @@
name: 'JS benchmarks'
on:
workflow_run:
workflows: ['Package the js repl as a binary artifact']
branches: [master]
types: [completed]
jobs:
js-benchmarks:
runs-on: ['js-benchmarks', 'self-hosted', '${{ matrix.runner }}']
if: ${{ github.repository == 'LadybirdBrowser/ladybird' && github.event.workflow_run.conclusion == 'success' }}
strategy:
fail-fast: false
matrix:
os_name: ['Linux']
runner: ['ubuntu-24.04-internal']
arch: ['x86_64']
package_type: ['Linux-x86_64']
include:
- os_name: 'macOS'
runner: 'macos-15'
arch: 'arm64'
package_type: 'macOS-arm64'
permissions:
actions: read
contents: read
steps:
- name: 'Checkout LadybirdBrowser/js-benchmarks'
uses: actions/checkout@v4
with:
repository: LadybirdBrowser/js-benchmarks
path: js-benchmarks
- name: 'Install dependencies'
if: ${{ matrix.os_name == 'Linux' }}
shell: bash
run: |
sudo apt-get update -y
sudo apt-get install -y python3-venv
- name: 'Download JS repl artifact'
id: download-artifact
uses: dawidd6/action-download-artifact@v9
with:
run_id: ${{ github.event.workflow_run.id }}
name: ladybird-js-${{ matrix.package_type }}
path: js-repl
- name: 'Extract JS repl'
shell: bash
run: |
cd js-repl
tar -xvzf ladybird-js-${{ matrix.os_name }}-${{ matrix.arch }}.tar.gz
- name: 'Run the JS benchmarks'
shell: bash
run: |
cd js-benchmarks
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
./run.py --executable=${{ github.workspace }}/js-repl/bin/js --iterations=5
- name: 'Save results as an artifact'
uses: actions/upload-artifact@v4
with:
name: js-benchmarks-results-${{ matrix.os_name }}-${{ matrix.arch }}
path: js-benchmarks/results.json
retention-days: 90
- name: 'Call webhook'
shell: bash
run: |
echo '{
"commit": "${{ github.event.workflow_run.head_sha }}",
"os": "${{ matrix.os_name }}",
"arch": "${{ matrix.arch }}",
"artifact": "js-benchmarks-results-${{ matrix.os_name }}-${{ matrix.arch }}",
"artifact_run_id": "${{ github.run_id }}"
}' > request.json
curl \
--fail \
--silent \
--show-error \
--header 'Content-Type: application/json' \
--header "X-Hub-Signature-256: sha256=$(openssl dgst -sha256 -hmac '${{ secrets.JS_BENCHMARKS_WEBHOOK_SECRET }}' request.json | cut -d' ' -f2)" \
--data-binary '@request.json' \
'${{ secrets.JS_BENCHMARKS_WEBHOOK_URL }}'

View File

@ -3,23 +3,25 @@ name: Lagom Template
on:
workflow_call:
inputs:
toolchain:
required: true
type: string
os_name:
required: true
type: string
os:
required: true
type: string
fuzzer:
required: false
type: string
default: 'NO_FUZZ'
clang_plugins:
required: false
type: boolean
default: false
toolchain:
required: true
type: string
os_name:
required: true
type: string
runner:
required: true
type: string
arch:
required: true
type: string
build_preset:
required: true
type: string
clang_plugins:
required: false
type: boolean
default: false
env:
# runner.workspace = /home/runner/work/ladybird
@ -27,7 +29,6 @@ env:
LADYBIRD_SOURCE_DIR: ${{ github.workspace }}
CCACHE_DIR: ${{ github.workspace }}/.ccache
VCPKG_ROOT: ${{ github.workspace }}/Build/vcpkg
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
# Use the compiler version for the ccache compiler hash. Otherwise, if plugins are enabled, the plugin .so files
# are included in the hash. This results in clean builds on every run as the .so files are rebuilt.
@ -37,7 +38,7 @@ env:
jobs:
CI:
runs-on: ${{ inputs.os }}
runs-on: ${{ inputs.runner }}
steps:
# Pull requests can trail behind `master` and can cause breakage if merging before running the CI checks on an updated branch.
@ -55,20 +56,26 @@ jobs:
uses: ./.github/actions/setup
with:
os: ${{ inputs.os_name }}
arch: 'Lagom'
arch: ${{ inputs.arch }}
toolchain: ${{ inputs.toolchain }}
# === PREPARE FOR BUILDING ===
- name: Assign Build Parameters
id: 'build-parameters'
run: |
if ${{ inputs.os_name == 'Linux' }} ; then
CMAKE_OPTIONS="-DENABLE_QT=ON"
if ${{ inputs.toolchain == 'Swift' }} ; then
echo "host_cc=$(swiftly use --print-location)/usr/bin/clang" >> "$GITHUB_OUTPUT"
echo "host_cxx=$(swiftly use --print-location)/usr/bin/clang++" >> "$GITHUB_OUTPUT"
CMAKE_OPTIONS="$CMAKE_OPTIONS -DENABLE_SWIFT=ON"
elif ${{ inputs.os_name == 'Linux' }} ; then
if ${{ inputs.toolchain == 'Clang' }} ; then
echo "host_cc=clang-19" >> "$GITHUB_OUTPUT"
echo "host_cxx=clang++-19" >> "$GITHUB_OUTPUT"
echo "host_cc=clang-20" >> "$GITHUB_OUTPUT"
echo "host_cxx=clang++-20" >> "$GITHUB_OUTPUT"
elif ${{ inputs.toolchain == 'GNU' }} ; then
echo "host_cc=gcc-13" >> "$GITHUB_OUTPUT"
echo "host_cxx=g++-13" >> "$GITHUB_OUTPUT"
echo "host_cc=gcc-14" >> "$GITHUB_OUTPUT"
echo "host_cxx=g++-14" >> "$GITHUB_OUTPUT"
fi
elif ${{ inputs.os_name == 'macOS' }} ; then
echo "host_cc=$(xcrun --find clang)" >> "$GITHUB_OUTPUT"
@ -76,23 +83,34 @@ jobs:
fi
if ${{ inputs.clang_plugins }} ; then
echo "ccache_key=${{ inputs.fuzzer }}-CLANG_PLUGINS" >> "$GITHUB_OUTPUT"
echo "cmake_options=-DENABLE_CLANG_PLUGINS=ON" >> "$GITHUB_OUTPUT"
echo "ccache_key=${{ inputs.build_preset }}-CLANG_PLUGINS" >> "$GITHUB_OUTPUT"
CMAKE_OPTIONS="$CMAKE_OPTIONS -DENABLE_CLANG_PLUGINS=ON"
else
echo "ccache_key=${{ inputs.fuzzer }}" >> "$GITHUB_OUTPUT"
echo "cmake_options=" >> "$GITHUB_OUTPUT"
echo "ccache_key=${{ inputs.build_preset }}" >> "$GITHUB_OUTPUT"
if ${{ inputs.os_name == 'Linux' && inputs.arch == 'arm64' }} ; then
# FIXME: https://github.com/WebAssembly/wabt/issues/2533
# wabt doesn't have binary releases for arm64 Linux
PKGCONFIG=$(which pkg-config)
CMAKE_OPTIONS="$CMAKE_OPTIONS -DPKG_CONFIG_EXECUTABLE=$PKGCONFIG"
else
CMAKE_OPTIONS="$CMAKE_OPTIONS -DINCLUDE_WASM_SPEC_TESTS=ON -DWASM_SPEC_TEST_SKIP_FORMATTING=ON"
fi
fi
echo "cmake_options=$CMAKE_OPTIONS" >> "$GITHUB_OUTPUT"
- name: Restore Caches
uses: ./.github/actions/cache-restore
id: 'cache-restore'
with:
runner_label: ${{ inputs.runner }}
os: ${{ inputs.os_name }}
arch: 'Lagom'
arch: ${{ inputs.arch }}
toolchain: ${{ inputs.toolchain }}
cache_key_extra: ${{ steps.build-parameters.outputs.ccache_key }}
ccache_path: ${{ env.CCACHE_DIR }}
download_cache_path: ${{ github.workspace }}/Build/caches
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
- name: Set dynamic environment variables
run: |
@ -106,19 +124,17 @@ jobs:
run: sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
- name: Create Build Environment
if: ${{ inputs.fuzzer == 'NO_FUZZ' }}
if: ${{ inputs.build_preset != 'Fuzzers_CI' }}
working-directory: ${{ github.workspace }}
run: |
cmake --preset Sanitizer_CI -B Build \
-DINCLUDE_WASM_SPEC_TESTS=ON \
-DWASM_SPEC_TEST_SKIP_FORMATTING=ON \
cmake --preset ${{ inputs.build_preset }} -B Build \
${{ steps.build-parameters.outputs.cmake_options }} \
-DPython3_EXECUTABLE=${{ env.pythonLocation }}/bin/python \
-DCMAKE_C_COMPILER=${{ steps.build-parameters.outputs.host_cc }} \
-DCMAKE_CXX_COMPILER=${{ steps.build-parameters.outputs.host_cxx }}
- name: Create Build Environment
if: ${{ inputs.fuzzer == 'FUZZ' }}
if: ${{ inputs.build_preset == 'Fuzzers_CI' }}
working-directory: ${{ github.workspace }}
run: |
set -e
@ -128,13 +144,11 @@ jobs:
-DINSTALL_LAGOM_TOOLS=ON \
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/Build/tools-install \
-DPython3_EXECUTABLE=${{ env.pythonLocation }}/bin/python \
-DCMAKE_C_COMPILER=gcc-13 \
-DCMAKE_CXX_COMPILER=g++-13 \
-Dpackage=LagomTools
ninja -C ${{ github.workspace }}/Build/tools-build install
cmake --preset Fuzzers_CI -B Build \
cmake --preset ${{ inputs.build_preset }} -B Build \
-DPython3_EXECUTABLE=${{ env.pythonLocation }}/bin/python \
-DCMAKE_C_COMPILER=${{ steps.build-parameters.outputs.host_cc }} \
-DCMAKE_CXX_COMPILER=${{ steps.build-parameters.outputs.host_cxx }} \
@ -149,38 +163,30 @@ jobs:
cmake --build .
cmake --install . --strip --prefix ${{ github.workspace }}/Install
- name: Enable the Ladybird Qt chrome
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
- name: Enable the Ladybird AppKit chrome
if: ${{ inputs.os_name == 'macOS' && inputs.build_preset == 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}
run: cmake -B Build -DENABLE_QT=ON
run: cmake -B Build -DENABLE_QT=OFF
- name: Build the Ladybird Qt chrome
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
working-directory: ${{ github.workspace }}/Build
run: cmake --build .
- name: Enable the AppKit chrome with Swift files
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
working-directory: ${{ github.workspace }}
# FIXME: Don't force release build after https://github.com/LadybirdBrowser/ladybird/issues/1101 is fixed
run: cmake -B Build -DENABLE_QT=OFF -DENABLE_SWIFT=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build the AppKit chrome with Swift files
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
- name: Build the Ladybird AppKit chrome
if: ${{ inputs.os_name == 'macOS' && inputs.build_preset == 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}/Build
run: cmake --build .
- name: Save Caches
uses: ./.github/actions/cache-save
with:
arch: 'Lagom'
runner_label: ${{ inputs.runner }}
arch: ${{ inputs.arch }}
ccache_path: ${{ env.CCACHE_DIR }}
ccache_primary_key: ${{ steps.cache-restore.outputs.ccache_primary_key }}
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
vcpkg_cache_primary_key: ${{ steps.cache-restore.outputs.vcpkg_cache_primary_key }}
# === TEST ===
- name: Test
if: ${{ inputs.fuzzer == 'NO_FUZZ' }}
if: ${{ inputs.build_preset == 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}
run: ctest --preset Sanitizer --output-on-failure --test-dir Build --timeout 1800
env:
@ -189,17 +195,24 @@ jobs:
ASAN_OPTIONS: 'log_path=${{ github.workspace }}/asan.log'
UBSAN_OPTIONS: 'log_path=${{ github.workspace }}/ubsan.log'
- name: Test
if: ${{ inputs.build_preset != 'Fuzzers_CI' && inputs.build_preset != 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}
run: ctest --output-on-failure --test-dir Build --timeout 1800
env:
TESTS_ONLY: 1
- name: Upload LibWeb Test Artifacts
if: ${{ always() && inputs.fuzzer == 'NO_FUZZ' }}
if: ${{ always() && inputs.build_preset != 'Fuzzers_CI' }}
uses: actions/upload-artifact@v4
with:
name: libweb-test-artifacts-${{ inputs.os_name }}-${{inputs.fuzzer}}-${{inputs.toolchain}}-${{inputs.clang-plugins}}
name: libweb-test-artifacts-${{ inputs.os_name }}-${{inputs.build_preset}}-${{inputs.toolchain}}-${{inputs.clang-plugins}}
path: ${{ github.workspace }}/Build/UI/Headless/test-dumps
retention-days: 0
if-no-files-found: ignore
- name: Sanitizer Output
if: ${{ !cancelled() && inputs.fuzzer == 'NO_FUZZ' }}
if: ${{ !cancelled() && inputs.build_preset == 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}
run: |
log_output=$(find . -maxdepth 1 \( -name 'asan.log.*' -o -name 'ubsan.log.*' \) -exec cat {} \; )
@ -211,7 +224,7 @@ jobs:
fi
- name: Lints
if: ${{ inputs.os_name == 'Linux' && inputs.fuzzer == 'NO_FUZZ' }}
if: ${{ inputs.os_name == 'Linux' && inputs.build_preset == 'Sanitizer_CI' }}
working-directory: ${{ github.workspace }}
run: |
set -e

View File

@ -50,16 +50,18 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y ninja-build unzip gcc-13 g++-13 jq wget curl zip tar autoconf autoconf-archive automake nasm pkg-config libgl1-mesa-dev rsync
sudo apt-get update -y
sudo apt-get install -y ninja-build unzip clang-20 clang++-20 jq curl zip tar autoconf autoconf-archive automake nasm pkg-config libgl1-mesa-dev rsync
test -e /opt/wabt-1.0.35 || (
cd /tmp
wget https://github.com/WebAssembly/wabt/releases/download/1.0.35/wabt-1.0.35-ubuntu-20.04.tar.gz
curl -f -L -o wabt-1.0.35-ubuntu-20.04.tar.gz https://github.com/WebAssembly/wabt/releases/download/1.0.35/wabt-1.0.35-ubuntu-20.04.tar.gz
sudo tar xf wabt-1.0.35-ubuntu-20.04.tar.gz -C /opt
rm wabt-1.0.35-ubuntu-20.04.tar.gz
)
# FIXME: Just use the setup action
./Toolchain/BuildVcpkg.sh --ci
./Toolchain/BuildVcpkg.py --ci
- name: Setup Python
uses: actions/setup-python@v5
@ -72,12 +74,10 @@ jobs:
python -m pip install --upgrade pip
pip install -r libjs-test262/requirements.txt
- name: Check versions
run: set +e; g++ --version; g++-13 --version; python --version; python3 --version; ninja --version
- name: Restore Caches
uses: ./.github/actions/cache-restore
with:
runner_label: test262-runner
os: 'Linux'
arch: 'Lagom'
download_cache_path: ${{ github.workspace }}/libjs-test262/Build/caches
@ -94,11 +94,11 @@ jobs:
export HOME=${{ github.workspace }}/home
mkdir -p $HOME
env PATH="/opt/wabt-1.0.35/bin:$PATH" \
CC=gcc-13 \
CXX=g++-13 \
CC=clang-20 \
CXX=clang++-20 \
cmake --preset CI -B libjs-test262/Build \
-DCMAKE_C_COMPILER=gcc-13 \
-DCMAKE_CXX_COMPILER=g++-13 \
-DCMAKE_C_COMPILER=clang-20 \
-DCMAKE_CXX_COMPILER=clang++-20 \
-DWASM_SPEC_TEST_SKIP_FORMATTING=ON \
-DINCLUDE_WASM_SPEC_TESTS=ON \
-DENABLE_GUI_TARGETS=OFF
@ -148,7 +148,7 @@ jobs:
run: ./libjs-test262/per_file_result_diff.py -o old-libjs-data/wasm/per-file-master.json -n libjs-data/wasm/per-file-master.json
- name: Deploy to GitHub
uses: JamesIves/github-pages-deploy-action@v4.7.2
uses: JamesIves/github-pages-deploy-action@v4.7.3
with:
git-config-name: LadybirdBot
git-config-email: ladybirdbot@ladybird.org

View File

@ -15,7 +15,7 @@ jobs:
run: |
set -e
brew install curl flake8 llvm@19 ninja optipng shellcheck swift-format unzip
brew install black curl llvm@20 ninja optipng shellcheck swift-format unzip
# Note: gn isn't available in homebrew :(
# Corresponds to https://gn.googlesource.com/gn/+/225e90c5025bf74f41dbee60d9cde4512c846fe7

View File

@ -7,7 +7,7 @@ on: [pull_request_target]
jobs:
lint:
runs-on: ubuntu-24.04
runs-on: blacksmith-2vcpu-ubuntu-2404
if: github.repository == 'LadybirdBrowser/ladybird'
steps:

View File

@ -12,7 +12,7 @@ on:
jobs:
auto-labeler:
runs-on: ubuntu-24.04
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: read
pull-requests: write

View File

@ -11,7 +11,6 @@ env:
LADYBIRD_SOURCE_DIR: ${{ github.workspace }}
CCACHE_DIR: ${{ github.workspace }}/.ccache
VCPKG_ROOT: ${{ github.workspace }}/Build/vcpkg
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || format('{0}-{1}', github.ref, github.run_number) }}
@ -56,6 +55,7 @@ jobs:
cache_key_extra: 'Nightly Android'
ccache_path: ${{ env.CCACHE_DIR }}
download_cache_path: ${{ github.workspace }}/Build/caches
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
- name: Assign Build Parameters
id: 'build-parameters'
@ -103,3 +103,5 @@ jobs:
arch: 'Lagom'
ccache_path: ${{ env.CCACHE_DIR }}
ccache_primary_key: ${{ steps.cache-restore.outputs.ccache_primary_key }}
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
vcpkg_cache_primary_key: ${{ steps.cache-restore.outputs.vcpkg_cache_primary_key }}

70
.github/workflows/nightly-lagom.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Nightly Lagom
on:
# Automatically run at the end of every day.
schedule:
- cron: '0 0 * * *'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# CI matrix - runs the job in lagom-template.yml with different configurations.
Lagom:
if: github.repository == 'LadybirdBrowser/ladybird'
strategy:
fail-fast: false
matrix:
os_name: ['Linux']
arch: ['arm64']
build_preset: ['Sanitizer_CI']
toolchain: ['Clang']
clang_plugins: [false]
runner: ['blacksmith-8vcpu-ubuntu-2404-arm']
include:
- os_name: 'Linux'
arch: 'x86_64'
build_preset: 'Distribution_CI'
toolchain: 'GNU'
clang_plugins: false
runner: 'blacksmith-8vcpu-ubuntu-2404'
- os_name: 'macOS'
arch: 'arm64'
build_preset: 'Distribution_CI'
toolchain: 'Clang'
clang_plugins: false
runner: 'macos-15'
- os_name: 'Linux'
arch: 'arm64'
build_preset: 'Distribution_CI'
toolchain: 'Clang'
clang_plugins: false
runner: 'blacksmith-8vcpu-ubuntu-2404-arm'
- os_name: 'Linux'
arch: 'x86_64'
build_preset: 'Sanitizer_CI'
toolchain: 'Swift'
clang_plugins: false
runner: 'blacksmith-8vcpu-ubuntu-2404'
- os_name: 'macOS'
arch: 'arm64'
build_preset: 'Sanitizer_CI'
toolchain: 'Swift'
clang_plugins: false
runner: 'macos-15'
uses: ./.github/workflows/lagom-template.yml
with:
toolchain: ${{ matrix.toolchain }}
os_name: ${{ matrix.os_name }}
runner: ${{ matrix.runner }}
arch: ${{ matrix.arch }}
build_preset: ${{ matrix.build_preset }}
clang_plugins: ${{ matrix.clang_plugins }}

74
.github/workflows/nightly-windows.yml vendored Normal file
View File

@ -0,0 +1,74 @@
name: Nightly Windows
on:
# Automatically run at the end of every day.
schedule:
- cron: '0 0 * * *'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# runner.workspace = /home/runner/work/ladybird
# github.workspace = /home/runner/work/ladybird/ladybird
LADYBIRD_SOURCE_DIR: ${{ github.workspace }}
VCPKG_ROOT: ${{ github.workspace }}/Build/vcpkg
jobs:
CI:
if: github.repository == 'LadybirdBrowser/ladybird'
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
if: ${{ github.event_name != 'pull_request' }}
- uses: actions/checkout@v4
if: ${{ github.event_name == 'pull_request' }}
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: Set Up Environment
uses: ./.github/actions/setup
with:
os: 'Windows'
arch: 'x86_64'
toolchain: 'ClangCL'
- name: Restore Caches
uses: ./.github/actions/cache-restore
id: 'cache-restore'
with:
runner_label: windows-2022
os: Windows
arch: x86_64
toolchain: ClangCL
cache_key_extra: windows_ci_ninja
download_cache_path: ${{ github.workspace }}/Build/caches
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
- name: Create Build Environment
working-directory: ${{ github.workspace }}
run: |
cmake --preset windows_ci_ninja
- name: Build
working-directory: ${{ github.workspace }}
run: |
cmake --build --preset windows_ci_ninja
- name: Save Caches
uses: ./.github/actions/cache-save
with:
runner_label: windows-2022
arch: x86_64
vcpkg_cache_path: ${{ github.workspace }}/Build/caches/vcpkg-binary-cache
vcpkg_cache_primary_key: ${{ steps.cache-restore.outputs.vcpkg_cache_primary_key }}
- name: Test
working-directory: ${{ github.workspace }}
run: ctest --preset windows_ci_ninja --timeout 1800
env:
TESTS_ONLY: 1

View File

@ -5,10 +5,11 @@ on:
- master
permissions:
contents: write
jobs:
build:
if: github.repository == 'LadybirdBrowser/ladybird'
runs-on: ubuntu-latest
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v4
with:

View File

@ -9,7 +9,7 @@ on:
jobs:
stale:
runs-on: ubuntu-24.04
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
actions: write # required for cache management (see https://github.com/actions/stale/issues/1133)
pull-requests: write

3
.gitignore vendored
View File

@ -27,6 +27,7 @@ output/
.vim/
.exrc
.helix/
.swift-version
# Environments
.venv/
@ -58,3 +59,5 @@ Meta/CMake/vcpkg/user-variables.cmake
# Keep last to ensure .DS_Store is never tracked, even if otherwise allowed by any exception above.
.DS_Store
__pycache__

View File

@ -35,14 +35,14 @@ import os
import ycm_core
DIR_OF_THIS_SCRIPT = os.path.abspath(os.path.dirname(__file__))
SOURCE_EXTENSIONS = ['.cpp', '.c']
SOURCE_EXTENSIONS = [".cpp", ".c"]
database = ycm_core.CompilationDatabase(os.path.join(DIR_OF_THIS_SCRIPT, 'Build/ladybird'))
database = ycm_core.CompilationDatabase(os.path.join(DIR_OF_THIS_SCRIPT, "Build/ladybird"))
def is_header_file(filename):
extension = os.path.splitext(filename)[1]
return extension in ['.h', '.hxx', '.hpp', '.hh']
return extension in [".h", ".hxx", ".hpp", ".hh"]
def find_corresponding_source_file(filename):
@ -56,7 +56,7 @@ def find_corresponding_source_file(filename):
def Settings(**kwargs): # noqa: N802
if kwargs['language'] != 'cfamily':
if kwargs["language"] != "cfamily":
return {}
# If the file is a header, try to find the corresponding source file and
# retrieve its flags from the compilation database if using one. This is
@ -64,14 +64,14 @@ def Settings(**kwargs): # noqa: N802
# In addition, use this source file as the translation unit. This makes it
# possible to jump from a declaration in the header file to its definition
# in the corresponding source file.
filename = find_corresponding_source_file(kwargs['filename'])
filename = find_corresponding_source_file(kwargs["filename"])
compilation_info = database.GetCompilationInfoForFile(filename)
if not compilation_info.compiler_flags_:
return {}
return {
'flags': list(compilation_info.compiler_flags_),
'include_paths_relative_to_dir': DIR_OF_THIS_SCRIPT,
'override_filename': filename
"flags": list(compilation_info.compiler_flags_),
"include_paths_relative_to_dir": DIR_OF_THIS_SCRIPT,
"override_filename": filename,
}

View File

@ -15,6 +15,7 @@
namespace AK {
namespace Detail {
// This type serves as the storage of 0-sized `AK::Array`s. While zero-length `T[0]`
// is accepted as a GNU extension, it causes problems with UBSan in Clang 16.
template<typename T>
@ -22,6 +23,7 @@ struct EmptyArrayStorage {
T& operator[](size_t) const { VERIFY_NOT_REACHED(); }
constexpr operator T*() const { return nullptr; }
};
}
template<typename T, size_t Size>
@ -148,11 +150,13 @@ template<typename T, typename... Types>
Array(T, Types...) -> Array<T, sizeof...(Types) + 1>;
namespace Detail {
template<typename T, size_t... Is>
constexpr auto integer_sequence_generate_array([[maybe_unused]] T const offset, IntegerSequence<T, Is...>) -> Array<T, sizeof...(Is)>
{
return { { (offset + Is)... } };
}
}
template<typename T, T N>
@ -163,11 +167,13 @@ constexpr auto iota_array(T const offset = {})
}
namespace Detail {
template<typename T, size_t N, size_t... Is>
constexpr auto to_array_impl(T (&&a)[N], IndexSequence<Is...>) -> Array<T, sizeof...(Is)>
{
return { { a[Is]... } };
}
}
template<typename T, size_t N>

View File

@ -8,18 +8,26 @@
#include <AK/Backtrace.h>
#include <AK/Format.h>
#include <AK/Platform.h>
#include <AK/StringBuilder.h>
#include <AK/StringView.h>
#ifdef AK_OS_WINDOWS
# include <Windows.h>
#endif
#if defined(AK_OS_ANDROID) && (__ANDROID_API__ >= 33)
# include <android/log.h>
# define EXECINFO_BACKTRACE
# define PRINT_ERROR(s) __android_log_write(ANDROID_LOG_WARN, "AK", (s))
#else
# define PRINT_ERROR(s) (void)fputs((s), stderr)
# include <stdio.h>
# define PRINT_ERROR(s) (void)::fputs((s), stderr)
#endif
#if defined(AK_HAS_BACKTRACE_HEADER)
#if defined(AK_HAS_STD_STACKTRACE)
# include <stacktrace>
# include <string>
#elif defined(AK_HAS_BACKTRACE_HEADER)
# include <AK/StringBuilder.h>
# include <AK/StringView.h>
# include <cxxabi.h>
#endif
@ -29,9 +37,17 @@
# define ERRORLN warnln
#endif
#if defined(AK_HAS_BACKTRACE_HEADER)
namespace {
ALWAYS_INLINE void dump_backtrace()
extern "C" {
#if defined(AK_HAS_STD_STACKTRACE)
void dump_backtrace()
{
// We assume the stacktrace implementation demangles symbols, as does microsoft/STL
PRINT_ERROR(std::to_string(std::stacktrace::current(2)).c_str());
PRINT_ERROR("\n");
}
#elif defined(AK_HAS_BACKTRACE_HEADER)
void dump_backtrace()
{
// Grab symbols and dso name for up to 256 frames
void* trace[256] = {};
@ -76,11 +92,13 @@ ALWAYS_INLINE void dump_backtrace()
}
free(syms);
}
#else
void dump_backtrace()
{
PRINT_ERROR("dump_backtrace() is not supported with the current compilation options.\n");
}
#endif
extern "C" {
bool ak_colorize_output(void)
{
#if defined(AK_OS_SERENITY) || defined(AK_OS_ANDROID)
@ -94,14 +112,43 @@ bool ak_colorize_output(void)
void ak_trap(void)
{
#if defined(AK_HAS_BACKTRACE_HEADER)
#if defined(AK_HAS_BACKTRACE_HEADER) || defined(AK_HAS_STD_STACKTRACE)
dump_backtrace();
#endif
__builtin_trap();
}
#ifndef AK_OS_WINDOWS
[[gnu::weak]] void ak_assertion_handler(char const* message);
#endif
using AssertionHandlerFunc = void (*)(char const*);
static AssertionHandlerFunc get_custom_assertion_handler()
{
#ifndef AK_OS_WINDOWS
return ak_assertion_handler;
#else
// Windows doesn't support weak symbols as nicely as ELF platforms.
// Instead, rely on the fact that we only want this to be overridden from
// the main executable, and grab it from there if present.
if (HMODULE module = GetModuleHandle(nullptr)) {
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-function-type-mismatch"
auto handler = reinterpret_cast<AssertionHandlerFunc>(GetProcAddress(module, "ak_assertion_handler"));
# pragma clang diagnostic pop
FreeLibrary(module);
return handler;
}
return nullptr;
#endif
}
void ak_verification_failed(char const* message)
{
if (auto assertion_handler = get_custom_assertion_handler()) {
assertion_handler(message);
}
if (ak_colorize_output())
ERRORLN("\033[31;1mVERIFICATION FAILED\033[0m: {}", message);
else
@ -112,6 +159,9 @@ void ak_verification_failed(char const* message)
void ak_assertion_failed(char const* message)
{
if (auto assertion_handler = get_custom_assertion_handler()) {
assertion_handler(message);
}
if (ak_colorize_output())
ERRORLN("\033[31;1mASSERTION FAILED\033[0m: {}", message);
else

View File

@ -6,6 +6,7 @@
#pragma once
extern "C" void dump_backtrace();
extern "C" bool ak_colorize_output(void);
extern "C" __attribute__((noreturn)) void ak_trap(void);

View File

@ -455,6 +455,7 @@ public:
return __atomic_is_lock_free(sizeof(m_value), &m_value);
}
};
}
#if USING_AK_GLOBALLY

View File

@ -17,38 +17,65 @@ size_t size_required_to_decode_base64(StringView input)
return simdutf::maximal_binary_length_from_base64(input.characters_without_null_termination(), input.length());
}
static ErrorOr<size_t, InvalidBase64> decode_base64_into_impl(StringView input, ByteBuffer& output, simdutf::base64_options options)
static constexpr simdutf::last_chunk_handling_options to_simdutf_last_chunk_handling(LastChunkHandling last_chunk_handling)
{
size_t output_length = output.size();
switch (last_chunk_handling) {
case LastChunkHandling::Loose:
return simdutf::last_chunk_handling_options::loose;
case LastChunkHandling::Strict:
return simdutf::last_chunk_handling_options::strict;
case LastChunkHandling::StopBeforePartial:
return simdutf::last_chunk_handling_options::stop_before_partial;
}
VERIFY_NOT_REACHED();
}
static ErrorOr<size_t, InvalidBase64> decode_base64_into_impl(StringView input, ByteBuffer& output, LastChunkHandling last_chunk_handling, simdutf::base64_options options)
{
static constexpr auto decode_up_to_bad_character = true;
auto output_length = output.size();
auto result = simdutf::base64_to_binary_safe(
input.characters_without_null_termination(),
input.length(),
reinterpret_cast<char*>(output.data()),
output_length,
options);
options,
to_simdutf_last_chunk_handling(last_chunk_handling),
decode_up_to_bad_character);
if (result.error != simdutf::SUCCESS && result.error != simdutf::OUTPUT_BUFFER_TOO_SMALL) {
output.resize((result.count / 4) * 3);
return InvalidBase64 {
.error = Error::from_string_literal("Invalid base64-encoded data"),
.valid_input_bytes = result.count,
};
auto error = [&]() {
switch (result.error) {
case simdutf::BASE64_EXTRA_BITS:
return Error::from_string_literal("Extra bits found at end of chunk");
case simdutf::BASE64_INPUT_REMAINDER:
return Error::from_string_literal("Invalid trailing data");
case simdutf::INVALID_BASE64_CHARACTER:
return Error::from_string_literal("Invalid base64 character");
default:
return Error::from_string_literal("Invalid base64-encoded data");
}
}();
return InvalidBase64 { .error = move(error), .valid_input_bytes = result.count };
}
VERIFY(output_length <= output.size());
output.resize(output_length);
return result.error == simdutf::SUCCESS ? input.length() : result.count;
return result.count;
}
static ErrorOr<ByteBuffer> decode_base64_impl(StringView input, simdutf::base64_options options)
static ErrorOr<ByteBuffer> decode_base64_impl(StringView input, LastChunkHandling last_chunk_handling, simdutf::base64_options options)
{
ByteBuffer output;
TRY(output.try_resize(size_required_to_decode_base64(input)));
if (auto result = decode_base64_into_impl(input, output, options); result.is_error())
if (auto result = decode_base64_into_impl(input, output, last_chunk_handling, options); result.is_error())
return result.release_error().error;
return output;
@ -68,24 +95,24 @@ static ErrorOr<String> encode_base64_impl(StringView input, simdutf::base64_opti
return String::from_utf8_without_validation(output);
}
ErrorOr<ByteBuffer> decode_base64(StringView input)
ErrorOr<ByteBuffer> decode_base64(StringView input, LastChunkHandling last_chunk_handling)
{
return decode_base64_impl(input, simdutf::base64_default);
return decode_base64_impl(input, last_chunk_handling, simdutf::base64_default);
}
ErrorOr<ByteBuffer> decode_base64url(StringView input)
ErrorOr<ByteBuffer> decode_base64url(StringView input, LastChunkHandling last_chunk_handling)
{
return decode_base64_impl(input, simdutf::base64_url);
return decode_base64_impl(input, last_chunk_handling, simdutf::base64_url);
}
ErrorOr<size_t, InvalidBase64> decode_base64_into(StringView input, ByteBuffer& output)
ErrorOr<size_t, InvalidBase64> decode_base64_into(StringView input, ByteBuffer& output, LastChunkHandling last_chunk_handling)
{
return decode_base64_into_impl(input, output, simdutf::base64_default);
return decode_base64_into_impl(input, output, last_chunk_handling, simdutf::base64_default);
}
ErrorOr<size_t, InvalidBase64> decode_base64url_into(StringView input, ByteBuffer& output)
ErrorOr<size_t, InvalidBase64> decode_base64url_into(StringView input, ByteBuffer& output, LastChunkHandling last_chunk_handling)
{
return decode_base64_into_impl(input, output, simdutf::base64_url);
return decode_base64_into_impl(input, output, last_chunk_handling, simdutf::base64_url);
}
ErrorOr<String> encode_base64(ReadonlyBytes input, OmitPadding omit_padding)

View File

@ -15,8 +15,14 @@ namespace AK {
size_t size_required_to_decode_base64(StringView);
ErrorOr<ByteBuffer> decode_base64(StringView);
ErrorOr<ByteBuffer> decode_base64url(StringView);
enum class LastChunkHandling {
Loose,
Strict,
StopBeforePartial,
};
ErrorOr<ByteBuffer> decode_base64(StringView, LastChunkHandling = LastChunkHandling::Loose);
ErrorOr<ByteBuffer> decode_base64url(StringView, LastChunkHandling = LastChunkHandling::Loose);
struct InvalidBase64 {
Error error;
@ -25,8 +31,8 @@ struct InvalidBase64 {
// On success, these return the number of input bytes that were decoded. This might be less than the
// string length if the output buffer was not large enough.
ErrorOr<size_t, InvalidBase64> decode_base64_into(StringView, ByteBuffer&);
ErrorOr<size_t, InvalidBase64> decode_base64url_into(StringView, ByteBuffer&);
ErrorOr<size_t, InvalidBase64> decode_base64_into(StringView, ByteBuffer&, LastChunkHandling = LastChunkHandling::Loose);
ErrorOr<size_t, InvalidBase64> decode_base64url_into(StringView, ByteBuffer&, LastChunkHandling = LastChunkHandling::Loose);
enum class OmitPadding {
No,

View File

@ -231,7 +231,7 @@ template<typename WordType>
ALWAYS_INLINE constexpr WordType sub_words(WordType word1, WordType word2, bool& carry)
{
if (!is_constant_evaluated()) {
#if __has_builtin(__builtin_subc) && !defined(AK_BUILTIN_SUBC_BROKEN)
#if __has_builtin(__builtin_subc)
WordType ncarry, output;
if constexpr (SameAs<WordType, unsigned int>)
output = __builtin_subc(word1, word2, carry, reinterpret_cast<unsigned int*>(&ncarry));

View File

@ -6,21 +6,16 @@
#include <AK/ByteBuffer.h>
#include <AK/ByteString.h>
#include <AK/DeprecatedFlyString.h>
#include <AK/Enumerate.h>
#include <AK/FlyString.h>
#include <AK/Format.h>
#include <AK/Function.h>
#include <AK/StdLibExtras.h>
#include <AK/StringView.h>
#include <AK/Utf8View.h>
#include <AK/Vector.h>
namespace AK {
bool ByteString::operator==(DeprecatedFlyString const& fly_string) const
{
return m_impl == fly_string.impl() || view() == fly_string.view();
}
bool ByteString::operator==(ByteString const& other) const
{
return m_impl == other.impl() || view() == other.view();
@ -56,16 +51,6 @@ bool ByteString::copy_characters_to_buffer(char* buffer, size_t buffer_size) con
return characters_to_copy == length();
}
ByteString ByteString::isolated_copy() const
{
if (m_impl->length() == 0)
return empty();
char* buffer;
auto impl = StringImpl::create_uninitialized(length(), buffer);
memcpy(buffer, m_impl->characters(), m_impl->length());
return ByteString(move(*impl));
}
ByteString ByteString::substring(size_t start, size_t length) const
{
if (!length)
@ -187,9 +172,9 @@ ByteString ByteString::repeated(char ch, size_t count)
if (!count)
return empty();
char* buffer;
auto impl = StringImpl::create_uninitialized(count, buffer);
auto impl = ByteStringImpl::create_uninitialized(count, buffer);
memset(buffer, ch, count);
return *impl;
return impl;
}
ByteString ByteString::repeated(StringView string, size_t count)
@ -197,92 +182,10 @@ ByteString ByteString::repeated(StringView string, size_t count)
if (!count || string.is_empty())
return empty();
char* buffer;
auto impl = StringImpl::create_uninitialized(count * string.length(), buffer);
auto impl = ByteStringImpl::create_uninitialized(count * string.length(), buffer);
for (size_t i = 0; i < count; i++)
__builtin_memcpy(buffer + i * string.length(), string.characters_without_null_termination(), string.length());
return *impl;
}
ByteString ByteString::bijective_base_from(size_t value, unsigned base, StringView map)
{
value++;
if (map.is_null())
map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"sv;
VERIFY(base >= 2 && base <= map.length());
// The '8 bits per byte' assumption may need to go?
Array<char, round_up_to_power_of_two(sizeof(size_t) * 8 + 1, 2)> buffer;
size_t i = 0;
do {
auto remainder = value % base;
auto new_value = value / base;
if (remainder == 0) {
new_value--;
remainder = map.length();
}
buffer[i++] = map[remainder - 1];
value = new_value;
} while (value > 0);
for (size_t j = 0; j < i / 2; ++j)
swap(buffer[j], buffer[i - j - 1]);
return ByteString { ReadonlyBytes(buffer.data(), i) };
}
ByteString ByteString::roman_number_from(size_t value)
{
if (value > 3999)
return ByteString::number(value);
StringBuilder builder;
while (value > 0) {
if (value >= 1000) {
builder.append('M');
value -= 1000;
} else if (value >= 900) {
builder.append("CM"sv);
value -= 900;
} else if (value >= 500) {
builder.append('D');
value -= 500;
} else if (value >= 400) {
builder.append("CD"sv);
value -= 400;
} else if (value >= 100) {
builder.append('C');
value -= 100;
} else if (value >= 90) {
builder.append("XC"sv);
value -= 90;
} else if (value >= 50) {
builder.append('L');
value -= 50;
} else if (value >= 40) {
builder.append("XL"sv);
value -= 40;
} else if (value >= 10) {
builder.append('X');
value -= 10;
} else if (value == 9) {
builder.append("IX"sv);
value -= 9;
} else if (value >= 5 && value <= 8) {
builder.append('V');
value -= 5;
} else if (value == 4) {
builder.append("IV"sv);
value -= 4;
} else if (value <= 3) {
builder.append('I');
value -= 1;
}
}
return builder.to_byte_string();
return impl;
}
bool ByteString::matches(StringView mask, Vector<MaskSpan>& mask_spans, CaseSensitivity case_sensitivity) const
@ -337,19 +240,37 @@ ByteString escape_html_entities(StringView html)
return builder.to_byte_string();
}
ByteString::ByteString(DeprecatedFlyString const& string)
: m_impl(string.impl())
ByteString::ByteString(FlyString const& string)
: m_impl(ByteStringImpl::create(string.bytes()))
{
}
ByteString ByteString::to_lowercase() const
{
return m_impl->to_lowercase();
if (!any_of(bytes(), is_ascii_upper_alpha))
return *this;
char* buffer = nullptr;
auto impl = ByteStringImpl::create_uninitialized(length(), buffer);
for (auto [i, character] : enumerate(view()))
buffer[i] = static_cast<char>(to_ascii_lowercase(character));
return impl;
}
ByteString ByteString::to_uppercase() const
{
return m_impl->to_uppercase();
if (!any_of(bytes(), is_ascii_lower_alpha))
return *this;
char* buffer = nullptr;
auto impl = ByteStringImpl::create_uninitialized(length(), buffer);
for (auto [i, character] : enumerate(view()))
buffer[i] = static_cast<char>(to_ascii_uppercase(character));
return impl;
}
ByteString ByteString::to_snakecase() const
@ -357,16 +278,6 @@ ByteString ByteString::to_snakecase() const
return StringUtils::to_snakecase(*this);
}
ByteString ByteString::to_titlecase() const
{
return StringUtils::to_titlecase(*this);
}
ByteString ByteString::invert_case() const
{
return StringUtils::invert_case(*this);
}
bool ByteString::operator==(char const* cstring) const
{
if (!cstring)
@ -387,16 +298,4 @@ Vector<size_t> ByteString::find_all(StringView needle) const
return StringUtils::find_all(*this, needle);
}
Utf8CodePointIterator ByteString::code_points() const&
{
return Utf8CodePointIterator { reinterpret_cast<u8 const*>(characters()), length() };
}
ErrorOr<ByteString> ByteString::from_utf8(ReadonlyBytes bytes)
{
if (!Utf8View(bytes).validate())
return Error::from_string_literal("ByteString::from_utf8: Input was not valid UTF-8");
return ByteString { *StringImpl::create(bytes) };
}
}

View File

@ -6,11 +6,11 @@
#pragma once
#include <AK/ByteStringImpl.h>
#include <AK/Format.h>
#include <AK/Forward.h>
#include <AK/RefPtr.h>
#include <AK/StringBuilder.h>
#include <AK/StringImpl.h>
#include <AK/StringUtils.h>
#include <AK/Traits.h>
@ -41,12 +41,12 @@ public:
~ByteString() = default;
ByteString()
: m_impl(StringImpl::the_empty_stringimpl())
: m_impl(ByteStringImpl::the_empty_stringimpl())
{
}
ByteString(StringView view)
: m_impl(*StringImpl::create(view.characters_without_null_termination(), view.length()))
: m_impl(ByteStringImpl::create(view.characters_without_null_termination(), view.length()))
{
}
@ -58,40 +58,35 @@ public:
ByteString(ByteString&& other)
: m_impl(move(other.m_impl))
{
other.m_impl = StringImpl::the_empty_stringimpl();
other.m_impl = ByteStringImpl::the_empty_stringimpl();
}
ByteString(char const* cstring, ShouldChomp shouldChomp = NoChomp)
: m_impl(*StringImpl::create(cstring, shouldChomp))
: m_impl(ByteStringImpl::create(cstring, shouldChomp))
{
}
ByteString(char const* cstring, size_t length, ShouldChomp shouldChomp = NoChomp)
: m_impl(*StringImpl::create(cstring, length, shouldChomp))
: m_impl(ByteStringImpl::create(cstring, length, shouldChomp))
{
}
explicit ByteString(ReadonlyBytes bytes, ShouldChomp shouldChomp = NoChomp)
: m_impl(*StringImpl::create(bytes, shouldChomp))
: m_impl(ByteStringImpl::create(bytes, shouldChomp))
{
}
ByteString(StringImpl const& impl)
ByteString(ByteStringImpl const& impl)
: m_impl(impl)
{
}
ByteString(NonnullRefPtr<StringImpl const>&& impl)
: m_impl(*move(impl))
ByteString(NonnullRefPtr<ByteStringImpl const>&& impl)
: m_impl(move(impl))
{
}
ByteString(DeprecatedFlyString const&);
static ErrorOr<ByteString> from_utf8(ReadonlyBytes);
static ErrorOr<ByteString> from_utf8(StringView string) { return from_utf8(string.bytes()); }
static ByteString must_from_utf8(StringView string) { return MUST(from_utf8(string)); }
static ByteString from_utf8_without_validation(StringView string) { return ByteString { string }; }
ByteString(FlyString const&);
template<
typename F,
@ -101,7 +96,7 @@ public:
static ReturnType create_and_overwrite(size_t length, F&& fill_function)
{
char* buffer;
auto impl = StringImpl::create_uninitialized(length, buffer);
auto impl = ByteStringImpl::create_uninitialized(length, buffer);
if constexpr (is_error_or)
TRY(fill_function(Bytes { buffer, length }));
@ -113,9 +108,6 @@ public:
[[nodiscard]] static ByteString repeated(char, size_t count);
[[nodiscard]] static ByteString repeated(StringView, size_t count);
[[nodiscard]] static ByteString bijective_base_from(size_t value, unsigned base = 26, StringView map = {});
[[nodiscard]] static ByteString roman_number_from(size_t value);
template<class SeparatorType, class CollectionType>
[[nodiscard]] static ByteString join(SeparatorType const& separator, CollectionType const& collection, StringView fmtstr = "{}"sv)
{
@ -127,6 +119,12 @@ public:
[[nodiscard]] bool matches(StringView mask, CaseSensitivity = CaseSensitivity::CaseInsensitive) const;
[[nodiscard]] bool matches(StringView mask, Vector<MaskSpan>&, CaseSensitivity = CaseSensitivity::CaseInsensitive) const;
template<Arithmetic T>
[[nodiscard]] static ByteString number(T value)
{
return formatted("{}", value);
}
template<Arithmetic T>
Optional<T> to_number(TrimWhitespace trim_whitespace = TrimWhitespace::Yes) const
{
@ -136,14 +134,9 @@ public:
[[nodiscard]] ByteString to_lowercase() const;
[[nodiscard]] ByteString to_uppercase() const;
[[nodiscard]] ByteString to_snakecase() const;
[[nodiscard]] ByteString to_titlecase() const;
[[nodiscard]] ByteString invert_case() const;
[[nodiscard]] bool is_whitespace() const { return StringUtils::is_whitespace(*this); }
[[nodiscard]] Utf8CodePointIterator code_points() const&;
[[nodiscard]] Utf8CodePointIterator code_points() const&& = delete;
[[nodiscard]] ByteString trim(StringView characters, TrimMode mode = TrimMode::Both) const
{
auto trimmed_view = StringUtils::trim(view(), characters, mode);
@ -228,8 +221,6 @@ public:
bool operator==(StringView) const;
bool operator==(DeprecatedFlyString const&) const;
bool operator<(ByteString const&) const;
bool operator>=(ByteString const& other) const { return !(*this < other); }
bool operator>=(char const* other) const { return !(*this < other); }
@ -240,14 +231,12 @@ public:
bool operator==(char const* cstring) const;
[[nodiscard]] ByteString isolated_copy() const;
[[nodiscard]] static ByteString empty()
{
return StringImpl::the_empty_stringimpl();
return ByteStringImpl::the_empty_stringimpl();
}
[[nodiscard]] NonnullRefPtr<StringImpl const> impl() const { return m_impl; }
[[nodiscard]] NonnullRefPtr<ByteStringImpl const> impl() const { return m_impl; }
ByteString& operator=(ByteString&& other)
{
@ -266,7 +255,7 @@ public:
template<OneOf<ReadonlyBytes, Bytes> T>
ByteString& operator=(T bytes)
{
m_impl = *StringImpl::create(bytes);
m_impl = ByteStringImpl::create(bytes);
return *this;
}
@ -294,12 +283,6 @@ public:
return vformatted(fmtstr.view(), variadic_format_parameters);
}
template<Arithmetic T>
[[nodiscard]] static ByteString number(T value)
{
return formatted("{}", value);
}
[[nodiscard]] StringView view() const& { return { characters(), length() }; }
[[nodiscard]] StringView view() const&& = delete;
@ -326,7 +309,7 @@ public:
}
private:
NonnullRefPtr<StringImpl const> m_impl;
NonnullRefPtr<ByteStringImpl const> m_impl;
};
template<>

92
AK/ByteStringImpl.cpp Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteStringImpl.h>
#include <AK/CharacterTypes.h>
#include <AK/StringHash.h>
#include <AK/kmalloc.h>
namespace AK {
static ByteStringImpl* s_the_empty_stringimpl = nullptr;
ByteStringImpl& ByteStringImpl::the_empty_stringimpl()
{
if (!s_the_empty_stringimpl) {
void* slot = kmalloc(sizeof(ByteStringImpl) + sizeof(char));
s_the_empty_stringimpl = new (slot) ByteStringImpl(ConstructTheEmptyStringImpl);
}
return *s_the_empty_stringimpl;
}
ByteStringImpl::ByteStringImpl(ConstructWithInlineBufferTag, size_t length)
: m_length(length)
{
}
ByteStringImpl::~ByteStringImpl() = default;
NonnullRefPtr<ByteStringImpl const> ByteStringImpl::create_uninitialized(size_t length, char*& buffer)
{
VERIFY(length);
void* slot = kmalloc(allocation_size_for_stringimpl(length));
VERIFY(slot);
auto new_stringimpl = adopt_ref(*new (slot) ByteStringImpl(ConstructWithInlineBuffer, length));
buffer = const_cast<char*>(new_stringimpl->characters());
buffer[length] = '\0';
return new_stringimpl;
}
NonnullRefPtr<ByteStringImpl const> ByteStringImpl::create(char const* cstring, size_t length, ShouldChomp should_chomp)
{
if (should_chomp) {
while (length) {
char last_ch = cstring[length - 1];
if (!last_ch || last_ch == '\n' || last_ch == '\r')
--length;
else
break;
}
}
if (!length)
return the_empty_stringimpl();
char* buffer;
auto new_stringimpl = create_uninitialized(length, buffer);
memcpy(buffer, cstring, length * sizeof(char));
return new_stringimpl;
}
NonnullRefPtr<ByteStringImpl const> ByteStringImpl::create(char const* cstring, ShouldChomp shouldChomp)
{
if (!cstring || !*cstring)
return the_empty_stringimpl();
return create(cstring, strlen(cstring), shouldChomp);
}
NonnullRefPtr<ByteStringImpl const> ByteStringImpl::create(ReadonlyBytes bytes, ShouldChomp shouldChomp)
{
return ByteStringImpl::create(reinterpret_cast<char const*>(bytes.data()), bytes.size(), shouldChomp);
}
unsigned ByteStringImpl::case_insensitive_hash() const
{
return case_insensitive_string_hash(characters(), length());
}
void ByteStringImpl::compute_hash() const
{
if (!length())
m_hash = 0;
else
m_hash = string_hash(characters(), m_length);
m_has_hash = true;
}
}

View File

@ -7,8 +7,8 @@
#pragma once
#include <AK/Badge.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/Span.h>
#include <AK/Types.h>
#include <AK/kmalloc.h>
@ -22,26 +22,21 @@ enum ShouldChomp {
size_t allocation_size_for_stringimpl(size_t length);
class StringImpl : public RefCounted<StringImpl> {
class ByteStringImpl : public RefCounted<ByteStringImpl> {
public:
static NonnullRefPtr<StringImpl const> create_uninitialized(size_t length, char*& buffer);
static RefPtr<StringImpl const> create(char const* cstring, ShouldChomp = NoChomp);
static RefPtr<StringImpl const> create(char const* cstring, size_t length, ShouldChomp = NoChomp);
static RefPtr<StringImpl const> create(ReadonlyBytes, ShouldChomp = NoChomp);
static RefPtr<StringImpl const> create_lowercased(char const* cstring, size_t length);
static RefPtr<StringImpl const> create_uppercased(char const* cstring, size_t length);
NonnullRefPtr<StringImpl const> to_lowercase() const;
NonnullRefPtr<StringImpl const> to_uppercase() const;
static NonnullRefPtr<ByteStringImpl const> create_uninitialized(size_t length, char*& buffer);
static NonnullRefPtr<ByteStringImpl const> create(char const* cstring, ShouldChomp = NoChomp);
static NonnullRefPtr<ByteStringImpl const> create(char const* cstring, size_t length, ShouldChomp = NoChomp);
static NonnullRefPtr<ByteStringImpl const> create(ReadonlyBytes, ShouldChomp = NoChomp);
void operator delete(void* ptr)
{
kfree_sized(ptr, allocation_size_for_stringimpl(static_cast<StringImpl*>(ptr)->m_length));
kfree_sized(ptr, allocation_size_for_stringimpl(static_cast<ByteStringImpl*>(ptr)->m_length));
}
static StringImpl& the_empty_stringimpl();
static ByteStringImpl& the_empty_stringimpl();
~StringImpl();
~ByteStringImpl();
size_t length() const { return m_length; }
// Includes NUL-terminator.
@ -56,7 +51,7 @@ public:
return characters()[i];
}
bool operator==(StringImpl const& other) const
bool operator==(ByteStringImpl const& other) const
{
if (length() != other.length())
return false;
@ -77,15 +72,11 @@ public:
unsigned case_insensitive_hash() const;
bool is_fly() const { return m_fly; }
void set_fly(Badge<DeprecatedFlyString>, bool fly) const { m_fly = fly; }
private:
enum ConstructTheEmptyStringImplTag {
ConstructTheEmptyStringImpl
};
explicit StringImpl(ConstructTheEmptyStringImplTag)
: m_fly(true)
explicit ByteStringImpl(ConstructTheEmptyStringImplTag)
{
m_inline_buffer[0] = '\0';
}
@ -93,25 +84,24 @@ private:
enum ConstructWithInlineBufferTag {
ConstructWithInlineBuffer
};
StringImpl(ConstructWithInlineBufferTag, size_t length);
ByteStringImpl(ConstructWithInlineBufferTag, size_t length);
void compute_hash() const;
size_t m_length { 0 };
mutable unsigned m_hash { 0 };
mutable bool m_has_hash { false };
mutable bool m_fly { false };
char m_inline_buffer[0];
};
inline size_t allocation_size_for_stringimpl(size_t length)
{
return sizeof(StringImpl) + (sizeof(char) * length) + sizeof(char);
return sizeof(ByteStringImpl) + (sizeof(char) * length) + sizeof(char);
}
template<>
struct Formatter<StringImpl> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, StringImpl const& value)
struct Formatter<ByteStringImpl> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, ByteStringImpl const& value)
{
return Formatter<StringView>::format(builder, { value.characters(), value.length() });
}
@ -122,5 +112,4 @@ struct Formatter<StringImpl> : Formatter<StringView> {
#if USING_AK_GLOBALLY
using AK::Chomp;
using AK::NoChomp;
using AK::StringImpl;
#endif

View File

@ -1,18 +1,18 @@
set(SOURCES
Assertions.cpp
Base64.cpp
ByteString.cpp
ByteStringImpl.cpp
CircularBuffer.cpp
ConstrainedStream.cpp
CountingStream.cpp
DOSPackedTime.cpp
DeprecatedFlyString.cpp
ByteString.cpp
Error.cpp
FloatingPointStringConversions.cpp
FlyString.cpp
Format.cpp
GenericLexer.cpp
Hex.cpp
JsonArray.cpp
JsonObject.cpp
JsonParser.cpp
JsonValue.cpp
@ -20,14 +20,12 @@ set(SOURCES
NumberFormat.cpp
OptionParser.cpp
Random.cpp
SipHash.cpp
StackInfo.cpp
Stream.cpp
String.cpp
StringBase.cpp
StringBuilder.cpp
StringFloatingPointConversions.cpp
StringImpl.cpp
StringUtils.cpp
StringView.cpp
Time.cpp
@ -45,22 +43,9 @@ endif()
serenity_lib(AK ak)
serenity_install_headers(AK)
serenity_install_sources(AK)
find_package(Backtrace)
include(stacktrace)
configure_file(Backtrace.h.in Backtrace.h @ONLY)
if (Backtrace_FOUND)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.30)
target_link_libraries(AK PRIVATE Backtrace::Backtrace)
else()
target_include_directories(AK PRIVATE ${Backtrace_INCLUDE_DIRS})
target_link_libraries(AK PRIVATE ${Backtrace_LIBRARIES})
endif()
else()
message(WARNING "Backtrace not found, stack traces will be unavailable")
endif()
link_stacktrace_library(AK STD_DEFINITION AK_HAS_STD_STACKTRACE)
find_package(simdutf REQUIRED)
swizzle_target_properties_for_swift(simdutf::simdutf)
@ -87,4 +72,27 @@ endif()
if (WIN32)
# FIXME: Windows on ARM
target_link_libraries(AK PRIVATE clang_rt.builtins-x86_64.lib)
target_link_libraries(AK PRIVATE Bcrypt.lib)
elseif (APPLE)
set(ASSERTION_HANDLER_VISIBILITY PRIVATE)
if (NOT BUILD_SHARED_LIBS)
set(ASSERTION_HANDLER_VISIBILITY INTERFACE)
endif()
target_link_options(AK ${ASSERTION_HANDLER_VISIBILITY} LINKER:-U,_ak_assertion_handler)
endif()
# Manually install AK headers
if (ENABLE_INSTALL_HEADERS)
install(
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMPONENT Lagom_Development
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h"
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/Debug.h
${CMAKE_CURRENT_BINARY_DIR}/Backtrace.h
COMPONENT Lagom_Development
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/AK"
)
endif()

View File

@ -127,6 +127,13 @@ public:
return m_detail->m_members[index];
}
Span<T const> span() const { return m_detail->m_members; }
Span<T> mutable_span()
{
copy();
return m_detail->m_members;
}
size_t capacity() const
{
return m_detail->m_members.capacity();

View File

@ -255,7 +255,7 @@ public:
constexpr Checked& operator+=(Checked const& other)
{
m_overflow |= other.m_overflow;
add(other.value());
add(other.value_unchecked());
return *this;
}
@ -268,7 +268,7 @@ public:
constexpr Checked& operator-=(Checked const& other)
{
m_overflow |= other.m_overflow;
sub(other.value());
sub(other.value_unchecked());
return *this;
}
@ -281,7 +281,7 @@ public:
constexpr Checked& operator*=(Checked const& other)
{
m_overflow |= other.m_overflow;
mul(other.value());
mul(other.value_unchecked());
return *this;
}
@ -294,7 +294,7 @@ public:
constexpr Checked& operator/=(Checked const& other)
{
m_overflow |= other.m_overflow;
div(other.value());
div(other.value_unchecked());
return *this;
}
@ -307,7 +307,7 @@ public:
constexpr Checked& operator%=(Checked const& other)
{
m_overflow |= other.m_overflow;
mod(other.value());
mod(other.value_unchecked());
return *this;
}
@ -434,7 +434,7 @@ template<typename T>
constexpr Checked<T> operator+(Checked<T> const& a, Checked<T> const& b)
{
Checked<T> c { a };
c.add(b.value());
c += b;
return c;
}
@ -442,7 +442,7 @@ template<typename T>
constexpr Checked<T> operator-(Checked<T> const& a, Checked<T> const& b)
{
Checked<T> c { a };
c.sub(b.value());
c -= b;
return c;
}
@ -450,7 +450,7 @@ template<typename T>
constexpr Checked<T> operator*(Checked<T> const& a, Checked<T> const& b)
{
Checked<T> c { a };
c.mul(b.value());
c *= b;
return c;
}
@ -458,7 +458,7 @@ template<typename T>
constexpr Checked<T> operator/(Checked<T> const& a, Checked<T> const& b)
{
Checked<T> c { a };
c.div(b.value());
c /= b;
return c;
}
@ -466,7 +466,7 @@ template<typename T>
constexpr Checked<T> operator%(Checked<T> const& a, Checked<T> const& b)
{
Checked<T> c { a };
c.mod(b.value());
c %= b;
return c;
}

View File

@ -126,11 +126,13 @@ consteval auto count_fmt_params(char const (&fmt)[N])
}
return result;
}
}
#endif
namespace AK::Format::Detail {
template<typename... Args>
struct CheckedFormatString {
template<size_t N>
@ -206,6 +208,7 @@ private:
StringView m_string;
};
}
namespace AK {

View File

@ -45,6 +45,9 @@ concept OneOf = IsOneOf<U, Ts...>;
template<typename U, typename... Ts>
concept OneOfIgnoringCV = IsOneOfIgnoringCV<U, Ts...>;
template<typename U, typename... Ts>
concept OneOfIgnoringCVReference = IsOneOfIgnoringCVReference<U, Ts...>;
template<typename T, template<typename...> typename S>
concept SpecializationOf = IsSpecializationOf<T, S>;
@ -126,7 +129,7 @@ template<typename T, typename ValueT>
concept IterableContainerOf = IterableContainer<T> && requires {
{
*declval<T>().begin()
} -> SameAs<ValueT>;
} -> SameAs<ValueT&>;
};
template<typename Func, typename... Args>
@ -167,6 +170,7 @@ concept CallableAs = Detail::IsCallableWithArguments<Func, R, Args...>;
#if !USING_AK_GLOBALLY
namespace AK {
#endif
using AK::Concepts::Arithmetic;
using AK::Concepts::ArrayLike;
@ -185,11 +189,13 @@ using AK::Concepts::IteratorFunction;
using AK::Concepts::IteratorPairWith;
using AK::Concepts::OneOf;
using AK::Concepts::OneOfIgnoringCV;
using AK::Concepts::OneOfIgnoringCVReference;
using AK::Concepts::SameAs;
using AK::Concepts::Signed;
using AK::Concepts::SpecializationOf;
using AK::Concepts::Unsigned;
using AK::Concepts::VoidFunction;
#if !USING_AK_GLOBALLY
}
#endif

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2022, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/DOSPackedTime.h>
namespace AK {
UnixDateTime time_from_packed_dos(DOSPackedDate date, DOSPackedTime time)
{
if (date.value == 0)
return UnixDateTime::from_unix_time_parts(first_dos_year, 1, 1, 0, 0, 0, 0);
return UnixDateTime::from_unix_time_parts(first_dos_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0);
}
DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day)
{
DOSPackedDate date;
date.year = year - first_dos_year;
date.month = month;
date.day = day;
return date;
}
DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second)
{
DOSPackedTime time;
time.hour = hour;
time.minute = minute;
time.second = second / 2;
return time;
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2022, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Time.h>
#include <AK/Types.h>
namespace AK {
union DOSPackedTime {
u16 value;
struct {
u16 second : 5;
u16 minute : 6;
u16 hour : 5;
};
};
static_assert(sizeof(DOSPackedTime) == 2);
union DOSPackedDate {
u16 value;
struct {
u16 day : 5;
u16 month : 4;
u16 year : 7;
};
};
static_assert(sizeof(DOSPackedDate) == 2);
inline constexpr u16 first_dos_year = 1980;
UnixDateTime time_from_packed_dos(DOSPackedDate, DOSPackedTime);
DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day);
DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second);
}
#if USING_AK_GLOBALLY
using AK::DOSPackedDate;
using AK::DOSPackedTime;
using AK::time_from_packed_dos;
using AK::to_packed_dos_date;
using AK::to_packed_dos_time;
#endif

View File

@ -6,6 +6,10 @@
#pragma once
#ifndef AK_STRINGBASE_VERIFY_LAUNDER_DEBUG
# cmakedefine01 AK_STRINGBASE_VERIFY_LAUNDER_DEBUG
#endif
#ifndef AUDIO_DEBUG
# cmakedefine01 AUDIO_DEBUG
#endif
@ -50,6 +54,10 @@
# cmakedefine01 CSS_TRANSITIONS_DEBUG
#endif
#ifndef DEVTOOLS_DEBUG
# cmakedefine01 DEVTOOLS_DEBUG
#endif
#ifndef DNS_DEBUG
# cmakedefine01 DNS_DEBUG
#endif
@ -106,6 +114,10 @@
# cmakedefine01 ICO_DEBUG
#endif
#ifndef IDB_DEBUG
# cmakedefine01 IDB_DEBUG
#endif
#ifndef IDL_DEBUG
# cmakedefine01 IDL_DEBUG
#endif
@ -250,10 +262,18 @@
# cmakedefine01 TOKENIZER_TRACE_DEBUG
#endif
#ifndef UPDATE_LAYOUT_DEBUG
# cmakedefine01 UPDATE_LAYOUT_DEBUG
#endif
#ifndef URL_PARSER_DEBUG
# cmakedefine01 URL_PARSER_DEBUG
#endif
#ifndef URL_PATTERN_DEBUG
# cmakedefine01 URL_PATTERN_DEBUG
#endif
#ifndef UTF8_DEBUG
# cmakedefine01 UTF8_DEBUG
#endif

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteString.h>
#include <AK/DeprecatedFlyString.h>
#include <AK/HashTable.h>
#include <AK/Optional.h>
#include <AK/Singleton.h>
#include <AK/StringUtils.h>
#include <AK/StringView.h>
namespace AK {
struct DeprecatedFlyStringImplTraits : public Traits<StringImpl const*> {
static unsigned hash(StringImpl const* s) { return s->hash(); }
static bool equals(StringImpl const* a, StringImpl const* b)
{
return *a == *b;
}
};
static Singleton<HashTable<StringImpl const*, DeprecatedFlyStringImplTraits>> s_table;
static HashTable<StringImpl const*, DeprecatedFlyStringImplTraits>& fly_impls()
{
return *s_table;
}
void DeprecatedFlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl)
{
fly_impls().remove(&impl);
}
DeprecatedFlyString::DeprecatedFlyString(ByteString const& string)
: m_impl(string.impl())
{
if (string.impl()->is_fly())
return;
auto it = fly_impls().find(string.impl());
if (it == fly_impls().end()) {
fly_impls().set(string.impl());
string.impl()->set_fly({}, true);
m_impl = string.impl();
} else {
VERIFY((*it)->is_fly());
m_impl = **it;
}
}
DeprecatedFlyString::DeprecatedFlyString(StringView string)
: m_impl(StringImpl::the_empty_stringimpl())
{
if (string.is_null())
return;
auto it = fly_impls().find(string.hash(), [&](auto& candidate) {
return string == *candidate;
});
if (it == fly_impls().end()) {
auto new_string = string.to_byte_string();
fly_impls().set(new_string.impl());
new_string.impl()->set_fly({}, true);
m_impl = new_string.impl();
} else {
VERIFY((*it)->is_fly());
m_impl = **it;
}
}
bool DeprecatedFlyString::equals_ignoring_ascii_case(StringView other) const
{
return StringUtils::equals_ignoring_ascii_case(view(), other);
}
bool DeprecatedFlyString::starts_with(StringView str, CaseSensitivity case_sensitivity) const
{
return StringUtils::starts_with(view(), str, case_sensitivity);
}
bool DeprecatedFlyString::ends_with(StringView str, CaseSensitivity case_sensitivity) const
{
return StringUtils::ends_with(view(), str, case_sensitivity);
}
DeprecatedFlyString DeprecatedFlyString::to_lowercase() const
{
return ByteString(*m_impl).to_lowercase();
}
bool DeprecatedFlyString::operator==(ByteString const& other) const
{
return m_impl == other.impl() || view() == other.view();
}
bool DeprecatedFlyString::operator==(StringView string) const
{
return view() == string;
}
bool DeprecatedFlyString::operator==(char const* string) const
{
return view() == string;
}
}

View File

@ -1,105 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/ByteString.h>
#include <AK/StringUtils.h>
namespace AK {
class DeprecatedFlyString {
public:
DeprecatedFlyString()
: m_impl(StringImpl::the_empty_stringimpl())
{
}
DeprecatedFlyString(DeprecatedFlyString const& other)
: m_impl(other.impl())
{
}
DeprecatedFlyString(DeprecatedFlyString&& other)
: m_impl(move(other.m_impl))
{
}
DeprecatedFlyString(ByteString const&);
DeprecatedFlyString(StringView);
DeprecatedFlyString(char const* string)
: DeprecatedFlyString(static_cast<ByteString>(string))
{
}
static DeprecatedFlyString from_fly_impl(NonnullRefPtr<StringImpl const> impl)
{
VERIFY(impl->is_fly());
DeprecatedFlyString string;
string.m_impl = move(impl);
return string;
}
DeprecatedFlyString& operator=(DeprecatedFlyString const& other)
{
m_impl = other.m_impl;
return *this;
}
DeprecatedFlyString& operator=(DeprecatedFlyString&& other)
{
m_impl = move(other.m_impl);
return *this;
}
bool is_empty() const { return !m_impl->length(); }
bool operator==(DeprecatedFlyString const& other) const { return m_impl == other.m_impl; }
bool operator==(ByteString const&) const;
bool operator==(StringView) const;
bool operator==(char const*) const;
NonnullRefPtr<StringImpl const> impl() const { return m_impl; }
char const* characters() const { return m_impl->characters(); }
size_t length() const { return m_impl->length(); }
ALWAYS_INLINE u32 hash() const { return m_impl->existing_hash(); }
ALWAYS_INLINE StringView view() const { return m_impl->view(); }
DeprecatedFlyString to_lowercase() const;
template<Arithmetic T>
Optional<T> to_number(TrimWhitespace trim_whitespace = TrimWhitespace::Yes) const
{
return view().to_number<T>(trim_whitespace);
}
bool equals_ignoring_ascii_case(StringView) const;
bool starts_with(StringView, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool ends_with(StringView, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
static void did_destroy_impl(Badge<StringImpl>, StringImpl&);
template<typename... Ts>
[[nodiscard]] ALWAYS_INLINE constexpr bool is_one_of(Ts&&... strings) const
{
return (... || this->operator==(forward<Ts>(strings)));
}
private:
NonnullRefPtr<StringImpl const> m_impl;
};
template<>
struct Traits<DeprecatedFlyString> : public DefaultTraits<DeprecatedFlyString> {
static unsigned hash(DeprecatedFlyString const& s) { return s.hash(); }
};
}
#if USING_AK_GLOBALLY
using AK::DeprecatedFlyString;
#endif

View File

@ -357,6 +357,12 @@ public:
return true;
}
[[nodiscard]] ReadonlySpan<T> flat_data() const
{
VERIFY(m_chunks.size() <= 1);
return m_chunks.is_empty() ? ReadonlySpan<T> {} : m_chunks.first().span();
}
DisjointChunks release_slice(size_t start, size_t length) & { return move(*this).slice(start, length); }
DisjointChunks release_slice(size_t start) & { return move(*this).slice(start); }

View File

@ -46,6 +46,7 @@ namespace AK {
*/
namespace DistinctNumericFeature {
enum Arithmetic { };
enum CastToBool { };
enum CastToUnderlying { };
@ -53,6 +54,7 @@ enum Comparison { };
enum Flags { };
enum Increment { };
enum Shift { };
};
template<typename T, typename X, typename... Opts>
@ -304,6 +306,7 @@ struct Formatter<DistinctNumeric<T, X, Opts...>> : Formatter<T> {
return Formatter<T>::format(builder, value.value());
}
};
}
#define AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, NAME, ...) \

View File

@ -11,6 +11,7 @@
namespace AK {
namespace Detail {
template<typename Iterable>
class Enumerator {
using IteratorType = decltype(declval<Iterable>().begin());
@ -50,6 +51,7 @@ private:
IteratorType m_iterator;
IteratorType const m_end;
};
}
template<typename T>

View File

@ -7,6 +7,7 @@
*/
#include <AK/Error.h>
#ifdef AK_OS_WINDOWS
# include <AK/ByteString.h>
# include <AK/HashMap.h>
@ -17,39 +18,10 @@
namespace AK {
Error Error::from_string_view_or_print_error_and_return_errno(StringView string_literal, [[maybe_unused]] int code)
{
return Error::from_string_view(string_literal);
}
#ifdef AK_OS_WINDOWS
Error Error::from_windows_error(u64 code)
Error Error::from_windows_error(u32 windows_error)
{
thread_local HashMap<u64, ByteString> s_windows_errors;
auto string = s_windows_errors.get(code);
if (string.has_value())
return Error::from_string_view(string->view());
char* message = nullptr;
auto size = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
static_cast<DWORD>(code),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPSTR>(&message),
0,
nullptr);
if (size == 0) {
static char buffer[128];
(void)snprintf(buffer, _countof(buffer), "Error 0x%08lX while getting text of error 0x%08llX", GetLastError(), code);
return Error::from_string_view({ buffer, _countof(buffer) });
}
auto& string_in_map = s_windows_errors.ensure(code, [message, size] { return ByteString { message, size }; });
LocalFree(message);
return Error::from_string_view(string_in_map.view());
return Error(static_cast<int>(windows_error), Error::Kind::Windows);
}
// This can be used both for generic Windows errors and for winsock errors because WSAGetLastError is forwarded to GetLastError.

View File

@ -6,6 +6,7 @@
#pragma once
#include <AK/Assertions.h>
#include <AK/StringView.h>
#include <AK/Variant.h>
#include <errno.h>
@ -14,100 +15,93 @@ namespace AK {
class [[nodiscard]] Error {
public:
ALWAYS_INLINE Error(Error&&) = default;
ALWAYS_INLINE Error& operator=(Error&&) = default;
enum class Kind : u8 {
Errno,
Syscall,
Windows,
StringLiteral,
};
static Error from_errno(int code)
{
VERIFY(code != 0);
return Error(code);
return Error(code, Kind::Errno);
}
#ifdef AK_OS_WINDOWS
static Error from_windows_error(u64 code);
static Error from_windows_error();
#endif
// NOTE: For calling this method from within kernel code, we will simply print
// the error message and return the errno code.
// For calling this method from userspace programs, we will simply return from
// the Error::from_string_view method!
static Error from_string_view_or_print_error_and_return_errno(StringView string_literal, int code);
static Error from_syscall(StringView syscall_name, int rc)
static Error from_syscall(StringView syscall_name, int code)
{
return Error(syscall_name, rc);
}
static Error from_string_view(StringView string_literal) { return Error(string_literal); }
template<OneOf<ByteString, DeprecatedFlyString, String, FlyString> T>
static Error from_string_view(T)
{
// `Error::from_string_view(ByteString::formatted(...))` is a somewhat common mistake, which leads to a UAF situation.
// If your string outlives this error and _isn't_ a temporary being passed to this function, explicitly call .view() on it to resolve to the StringView overload.
static_assert(DependentFalse<T>, "Error::from_string_view(String) is almost always a use-after-free");
VERIFY_NOT_REACHED();
return Error(syscall_name, code);
}
static Error copy(Error const& error)
{
return Error(error);
}
// NOTE: Prefer `from_string_literal` when directly typing out an error message:
// Prefer `from_string_literal` when directly typing out an error message:
//
// return Error::from_string_literal("Class: Some failure");
//
// If you need to return a static string based on a dynamic condition (like
// picking an error from an array), then prefer `from_string_view` instead.
// If you need to return a static string based on a dynamic condition (like picking an error from an array), then
// prefer `from_string_view` instead.
template<size_t N>
ALWAYS_INLINE static Error from_string_literal(char const (&string_literal)[N])
{
return from_string_view(StringView { string_literal, N - 1 });
}
// Note: Don't call this from C++; it's here for Jakt interop (as the name suggests).
template<SameAs<StringView> T>
ALWAYS_INLINE static Error __jakt_from_string_literal(T string)
static Error from_string_view(StringView string_literal)
{
return from_string_view(string);
return Error(string_literal);
}
template<OneOf<ByteString, String, FlyString> T>
static Error from_string_view(T)
{
// `Error::from_string_view(ByteString::formatted(...))` is a somewhat common mistake, which leads to a UAF
// situation. If your string outlives this error and _isn't_ a temporary being passed to this function,
// explicitly call .view() on it to resolve to the StringView overload.
static_assert(DependentFalse<T>, "Error::from_string_view(String) is almost always a use-after-free");
VERIFY_NOT_REACHED();
}
#ifdef AK_OS_WINDOWS
static Error from_windows_error(u32 windows_error);
static Error from_windows_error();
#endif
static Error copy(Error const& error)
{
return Error(error);
}
ALWAYS_INLINE Error(Error&&) = default;
ALWAYS_INLINE Error& operator=(Error&&) = default;
bool operator==(Error const& other) const
{
return m_code == other.m_code && m_string_literal == other.m_string_literal && m_syscall == other.m_syscall;
return m_code == other.m_code && m_string_literal == other.m_string_literal && m_kind == other.m_kind;
}
bool is_errno() const { return m_kind == Kind::Errno || m_kind == Kind::Syscall; }
bool is_windows_error() const { return m_kind == Kind::Windows; }
StringView string_literal() const { return m_string_literal; }
int code() const { return m_code; }
bool is_errno() const
{
return m_code != 0;
}
bool is_syscall() const
{
return m_syscall;
}
StringView string_literal() const
{
return m_string_literal;
}
protected:
Error(int code)
: m_code(code)
{
}
Kind kind() const { return m_kind; }
private:
Error(int code, Kind kind)
: m_code(code)
, m_kind(kind)
{
VERIFY(code != 0);
}
Error(StringView string_literal)
: m_string_literal(string_literal)
, m_kind(Kind::StringLiteral)
{
}
Error(StringView syscall_name, int rc)
Error(StringView syscall_name, int code)
: m_string_literal(syscall_name)
, m_code(-rc)
, m_syscall(true)
, m_code(code)
, m_kind(Kind::Syscall)
{
}
@ -115,10 +109,8 @@ private:
Error& operator=(Error const&) = default;
StringView m_string_literal;
int m_code { 0 };
bool m_syscall { false };
Kind m_kind {};
};
template<typename T, typename E>
@ -157,18 +149,14 @@ public:
{
}
#ifdef AK_OS_SERENITY
ErrorOr(ErrnoCode code)
: m_value_or_error(Error::from_errno(code))
{
}
#endif
T& value()
T& value() { return m_value_or_error.template get<T>(); }
T const& value() const { return m_value_or_error.template get<T>(); }
[[nodiscard]] ALWAYS_INLINE T const& value_or(T const& fallback) const
{
if (is_error())
return fallback;
return m_value_or_error.template get<T>();
}
T const& value() const { return m_value_or_error.template get<T>(); }
ErrorType& error() { return m_value_or_error.template get<ErrorType>(); }
ErrorType const& error() const { return m_value_or_error.template get<ErrorType>(); }

View File

@ -7,6 +7,7 @@
#pragma once
#include <AK/Concepts.h>
#include <AK/Optional.h>
#include <AK/Traits.h>
#include <AK/Types.h>
@ -36,10 +37,21 @@ requires(requires(TIterator it) { it.index(); })
return find_if(first, last, [&]<typename T>(T const& entry) { return Traits<T>::equals(entry, value); }).index();
}
template<IterableContainer Container, typename TUnaryPredicate>
[[nodiscard]] constexpr auto find_value(Container const& container, TUnaryPredicate&& pred)
-> Optional<decltype(*container.begin())>
{
auto it = find_if(container.begin(), container.end(), forward<TUnaryPredicate>(pred));
if (it != container.end())
return *it;
return {};
}
}
#if USING_AK_GLOBALLY
using AK::find;
using AK::find_if;
using AK::find_index;
using AK::find_value;
#endif

View File

@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/DeprecatedFlyString.h>
#include <AK/FlyString.h>
#include <AK/HashTable.h>
#include <AK/Singleton.h>
@ -57,19 +56,19 @@ FlyString::FlyString(String const& string)
return;
}
if (string.m_data->is_fly_string()) {
if (string.m_impl.data->is_fly_string()) {
m_data = string;
return;
}
auto it = all_fly_strings().find(string.m_data);
auto it = all_fly_strings().find(string.m_impl.data);
if (it == all_fly_strings().end()) {
m_data = string;
all_fly_strings().set(string.m_data);
string.m_data->set_fly_string(true);
all_fly_strings().set(string.m_impl.data);
string.m_impl.data->set_fly_string(true);
} else {
m_data.m_data = *it;
m_data.m_data->ref();
m_data.m_impl.data = *it;
m_data.m_impl.data->ref();
}
}
@ -79,16 +78,6 @@ FlyString& FlyString::operator=(String const& string)
return *this;
}
bool FlyString::is_empty() const
{
return bytes_as_string_view().is_empty();
}
unsigned FlyString::hash() const
{
return m_data.hash();
}
u32 FlyString::ascii_case_insensitive_hash() const
{
return case_insensitive_string_hash(reinterpret_cast<char const*>(bytes().data()), bytes().size());
@ -110,21 +99,6 @@ Utf8View FlyString::code_points() const
return Utf8View { bytes_as_string_view() };
}
ReadonlyBytes FlyString::bytes() const
{
return bytes_as_string_view().bytes();
}
StringView FlyString::bytes_as_string_view() const
{
return m_data.bytes();
}
bool FlyString::operator==(String const& other) const
{
return m_data == other;
}
bool FlyString::operator==(StringView string) const
{
return bytes_as_string_view() == string;
@ -135,11 +109,6 @@ bool FlyString::operator==(char const* string) const
return bytes_as_string_view() == string;
}
void FlyString::did_destroy_fly_string_data(Badge<Detail::StringData>, Detail::StringData const& string_data)
{
all_fly_strings().remove(&string_data);
}
Detail::StringBase FlyString::data(Badge<String>) const
{
return m_data;
@ -150,16 +119,6 @@ size_t FlyString::number_of_fly_strings()
return all_fly_strings().size();
}
DeprecatedFlyString FlyString::to_deprecated_fly_string() const
{
return DeprecatedFlyString(bytes_as_string_view());
}
ErrorOr<FlyString> FlyString::from_deprecated_fly_string(DeprecatedFlyString const& deprecated_fly_string)
{
return FlyString::from_utf8(deprecated_fly_string.view());
}
unsigned Traits<FlyString>::hash(FlyString const& fly_string)
{
return fly_string.hash();
@ -245,4 +204,13 @@ bool FlyString::ends_with_bytes(StringView bytes, CaseSensitivity case_sensitivi
return bytes_as_string_view().ends_with(bytes, case_sensitivity);
}
namespace Detail {
void did_destroy_fly_string_data(Badge<Detail::StringData>, Detail::StringData const& string_data)
{
all_fly_strings().remove(&string_data);
}
}
}

View File

@ -26,39 +26,35 @@ public:
static ErrorOr<FlyString> from_utf8(StringView);
static FlyString from_utf8_without_validation(ReadonlyBytes);
template<typename T>
requires(IsOneOf<RemoveCVReference<T>, ByteString, DeprecatedFlyString, FlyString, String>)
requires(IsOneOf<RemoveCVReference<T>, ByteString, FlyString, String>)
static ErrorOr<String> from_utf8(T&&) = delete;
FlyString(String const&);
FlyString& operator=(String const&);
[[nodiscard]] bool is_empty() const;
[[nodiscard]] unsigned hash() const;
[[nodiscard]] bool is_empty() const { return m_data.byte_count() == 0; }
[[nodiscard]] unsigned hash() const { return m_data.hash(); }
[[nodiscard]] u32 ascii_case_insensitive_hash() const;
explicit operator String() const;
String to_string() const;
[[nodiscard]] Utf8View code_points() const;
[[nodiscard]] ReadonlyBytes bytes() const;
[[nodiscard]] StringView bytes_as_string_view() const;
[[nodiscard]] ReadonlyBytes bytes() const { return m_data.bytes(); }
[[nodiscard]] StringView bytes_as_string_view() const { return m_data.bytes(); }
[[nodiscard]] ALWAYS_INLINE bool operator==(FlyString const& other) const { return m_data.raw({}) == other.m_data.raw({}); }
[[nodiscard]] bool operator==(String const&) const;
[[nodiscard]] ALWAYS_INLINE bool operator==(FlyString const& other) const { return m_data.raw(Badge<FlyString> {}) == other.m_data.raw(Badge<FlyString> {}); }
[[nodiscard]] bool operator==(String const& other) const { return m_data == other; }
[[nodiscard]] bool operator==(StringView) const;
[[nodiscard]] bool operator==(char const*) const;
[[nodiscard]] int operator<=>(FlyString const& other) const;
static void did_destroy_fly_string_data(Badge<Detail::StringData>, Detail::StringData const&);
[[nodiscard]] Detail::StringBase data(Badge<String>) const;
// This is primarily interesting to unit tests.
[[nodiscard]] static size_t number_of_fly_strings();
// FIXME: Remove these once all code has been ported to FlyString
[[nodiscard]] DeprecatedFlyString to_deprecated_fly_string() const;
static ErrorOr<FlyString> from_deprecated_fly_string(DeprecatedFlyString const&);
template<typename T>
requires(IsSame<RemoveCVReference<T>, StringView>)
static ErrorOr<String> from_deprecated_fly_string(T&&) = delete;
@ -89,21 +85,23 @@ public:
private:
friend class Optional<FlyString>;
explicit FlyString(nullptr_t)
: m_data(Detail::StringBase(nullptr))
explicit constexpr FlyString(nullptr_t)
: m_data(nullptr)
{
}
explicit FlyString(Detail::StringBase data)
explicit constexpr FlyString(Detail::StringBase data)
: m_data(move(data))
{
}
Detail::StringBase m_data;
bool is_invalid() const { return m_data.is_invalid(); }
constexpr bool is_invalid() const { return m_data.raw(Badge<FlyString> {}) == 0; }
};
void did_destroy_fly_string_data(Badge<Detail::StringData>, Detail::StringData const&);
template<>
class Optional<FlyString> : public OptionalBase<FlyString> {
template<typename U>
@ -112,38 +110,38 @@ class Optional<FlyString> : public OptionalBase<FlyString> {
public:
using ValueType = FlyString;
Optional() = default;
constexpr Optional() = default;
template<SameAs<OptionalNone> V>
Optional(V) { }
constexpr Optional(V) { }
Optional(Optional<FlyString> const& other)
constexpr Optional(Optional<FlyString> const& other)
{
if (other.has_value())
m_value = other.m_value;
}
Optional(Optional&& other)
: m_value(other.m_value)
constexpr Optional(Optional&& other)
: m_value(move(other.m_value))
{
}
template<typename U = FlyString>
requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
explicit(!IsConvertible<U&&, FlyString>) Optional(U&& value)
explicit(!IsConvertible<U&&, FlyString>) constexpr Optional(U&& value)
requires(!IsSame<RemoveCVReference<U>, Optional<FlyString>> && IsConstructible<FlyString, U &&>)
: m_value(forward<U>(value))
{
}
template<SameAs<OptionalNone> V>
Optional& operator=(V)
constexpr Optional& operator=(V)
{
clear();
return *this;
}
Optional& operator=(Optional const& other)
constexpr Optional& operator=(Optional const& other)
{
if (this != &other) {
clear();
@ -152,7 +150,7 @@ public:
return *this;
}
Optional& operator=(Optional&& other)
constexpr Optional& operator=(Optional&& other)
{
if (this != &other) {
clear();
@ -161,37 +159,37 @@ public:
return *this;
}
void clear()
constexpr void clear()
{
m_value = FlyString(nullptr);
}
[[nodiscard]] bool has_value() const
[[nodiscard]] constexpr bool has_value() const
{
return !m_value.is_invalid();
}
[[nodiscard]] FlyString& value() &
[[nodiscard]] constexpr FlyString& value() &
{
VERIFY(has_value());
return m_value;
}
[[nodiscard]] FlyString const& value() const&
[[nodiscard]] constexpr FlyString const& value() const&
{
VERIFY(has_value());
return m_value;
}
[[nodiscard]] FlyString value() &&
[[nodiscard]] constexpr FlyString value() &&
{
return release_value();
}
[[nodiscard]] FlyString release_value()
[[nodiscard]] constexpr FlyString release_value()
{
VERIFY(has_value());
FlyString released_value = m_value;
FlyString released_value = move(m_value);
clear();
return released_value;
}
@ -219,7 +217,8 @@ struct ASCIICaseInsensitiveFlyStringTraits : public Traits<String> {
[[nodiscard]] ALWAYS_INLINE AK::FlyString operator""_fly_string(char const* cstring, size_t length)
{
return AK::FlyString::from_utf8(AK::StringView(cstring, length)).release_value();
ASSERT(Utf8View(AK::StringView(cstring, length)).validate());
return AK::FlyString::from_utf8_without_validation({ cstring, length });
}
#if USING_AK_GLOBALLY

View File

@ -4,9 +4,13 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Assertions.h>
#include <AK/ByteString.h>
#include <AK/CharacterTypes.h>
#include <AK/Error.h>
#include <AK/Format.h>
#include <AK/GenericLexer.h>
#include <AK/HashMap.h>
#include <AK/IntegralMath.h>
#include <AK/LexicalPath.h>
#include <AK/String.h>
@ -102,7 +106,13 @@ ErrorOr<void> vformat_impl(TypeErasedFormatParams& params, FormatBuilder& builde
auto& parameter = params.parameters().at(specifier.index);
FormatParser argparser { specifier.flags };
TRY(parameter.formatter(params, builder, argparser, parameter.value));
TRY(parameter.visit([&]<typename T>(T const& value) {
if constexpr (IsSame<T, TypeErasedParameter::CustomType>) {
return value.formatter(params, builder, argparser, value.value);
} else {
return __format_value<T>(params, builder, argparser, &value);
}
}));
TRY(vformat_impl(params, builder, parser));
return {};
}
@ -507,6 +517,8 @@ ErrorOr<void> FormatBuilder::put_f64_with_precision(
TRY(format_builder.put_u64(static_cast<u64>(value), base, false, upper_case, false, use_separator, Align::Right, 0, ' ', sign_mode, is_negative));
value -= static_cast<i64>(value);
bool did_emit_decimals = false;
if (precision > 0) {
// FIXME: This is a terrible approximation but doing it properly would be a lot of work. If someone is up for that, a good
// place to start would be the following video from CppCon 2019:
@ -531,6 +543,7 @@ ErrorOr<void> FormatBuilder::put_f64_with_precision(
TRY(string_builder.try_append('.'));
TRY(string_builder.try_append('0' + (static_cast<u32>(value) % 10)));
did_emit_decimals = true;
}
}
@ -538,6 +551,22 @@ ErrorOr<void> FormatBuilder::put_f64_with_precision(
if (static_cast<u64>(value * 10.0) % 10 >= 5)
TRY(round_up_digits(string_builder));
if (did_emit_decimals && display_mode == RealNumberDisplayMode::Default) {
while (!string_builder.is_empty()) {
// Strip trailing zero decimals.
if (string_builder.string_view().ends_with('0')) {
string_builder.trim(1);
continue;
}
// Strip trailing decimal point.
if (string_builder.string_view().ends_with('.')) {
string_builder.trim(1);
break;
}
break;
}
}
return put_string(string_builder.string_view(), align, min_width, NumericLimits<size_t>::max(), fill);
}
@ -961,11 +990,11 @@ ErrorOr<void> Formatter<char>::format(FormatBuilder& builder, char value)
return formatter.format(builder, { &value, 1 });
}
}
ErrorOr<void> Formatter<wchar_t>::format(FormatBuilder& builder, wchar_t value)
ErrorOr<void> Formatter<char32_t>::format(FormatBuilder& builder, char32_t value)
{
if (m_mode == Mode::Binary || m_mode == Mode::BinaryUppercase || m_mode == Mode::Decimal || m_mode == Mode::Octal || m_mode == Mode::Hexadecimal || m_mode == Mode::HexadecimalUppercase) {
Formatter<u32> formatter { *this };
return formatter.format(builder, static_cast<u32>(value));
return formatter.format(builder, value);
} else {
StringBuilder codepoint;
codepoint.append_code_point(value);
@ -1087,6 +1116,56 @@ void vout(FILE* file, StringView fmtstr, TypeErasedFormatParams& params, bool ne
dbgln("vout() failed ({} written out of {}), error was {} ({})", retval, string.length(), error, strerror(error));
}
}
#if defined(AK_OS_WINDOWS)
ErrorOr<void> Formatter<Error>::format_windows_error(FormatBuilder& builder, Error const& error)
{
thread_local HashMap<u32, ByteString> windows_errors;
int code = error.code();
Optional<ByteString&> string = windows_errors.get(static_cast<u32>(code));
if (string.has_value()) {
return Formatter<StringView>::format(builder, string->view());
}
TCHAR* message = nullptr;
u32 size = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
static_cast<DWORD>(code),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
message,
0,
nullptr);
if (size == 0) {
auto format_error = GetLastError();
return Formatter<FormatString>::format(builder, "Error {:08x} when formatting code {:08x}"sv, format_error, code);
}
auto& string_in_map = windows_errors.ensure(code, [message, size] { return ByteString { message, size }; });
LocalFree(message);
return Formatter<StringView>::format(builder, string_in_map.view());
}
#else
ErrorOr<void> Formatter<Error>::format_windows_error(FormatBuilder&, Error const&)
{
VERIFY_NOT_REACHED();
}
#endif
ErrorOr<void> Formatter<Error>::format(FormatBuilder& builder, Error const& error)
{
switch (error.kind()) {
case Error::Kind::Syscall:
return Formatter<FormatString>::format(builder, "{}: {} (errno={})"sv, error.string_literal(), strerror(error.code()), error.code());
case Error::Kind::Errno:
return Formatter<FormatString>::format(builder, "{} (errno={})"sv, strerror(error.code()), error.code());
case Error::Kind::Windows:
return Formatter<Error>::format_windows_error(builder, error);
case Error::Kind::StringLiteral:
return Formatter<FormatString>::format(builder, "{}"sv, error.string_literal());
}
VERIFY_NOT_REACHED();
}
#ifdef AK_OS_ANDROID
static char const* s_log_tag_name = "Serenity";

View File

@ -53,95 +53,148 @@ concept Formattable = HasFormatter<T>;
constexpr size_t max_format_arguments = 256;
template<typename T>
ErrorOr<void> __format_value(TypeErasedFormatParams& params, FormatBuilder& builder, FormatParser& parser, void const* value)
{
Formatter<T> formatter;
formatter.parse(params, parser);
return formatter.format(builder, *static_cast<T const*>(value));
}
struct TypeErasedParameter {
enum class Type {
UInt8,
UInt16,
UInt32,
UInt64,
Int8,
Int16,
Int32,
Int64,
Custom
UnsignedInteger,
SignedInteger,
Boolean,
Character,
Float,
Double,
StringView,
CString,
CustomType
};
template<size_t size, bool is_unsigned>
static consteval Type get_type_from_size()
{
if constexpr (is_unsigned) {
if constexpr (size == 1)
return Type::UInt8;
if constexpr (size == 2)
return Type::UInt16;
if constexpr (size == 4)
return Type::UInt32;
if constexpr (size == 8)
return Type::UInt64;
} else {
if constexpr (size == 1)
return Type::Int8;
if constexpr (size == 2)
return Type::Int16;
if constexpr (size == 4)
return Type::Int32;
if constexpr (size == 8)
return Type::Int64;
}
struct CustomType {
void const* value;
ErrorOr<void> (*formatter)(TypeErasedFormatParams&, FormatBuilder&, FormatParser&, void const* value);
};
VERIFY_NOT_REACHED();
template<typename T>
static bool const IsChar = IsOneOf<T, char, wchar_t, char8_t, char16_t, char32_t>;
template<Unsigned U>
explicit constexpr TypeErasedParameter(U const& value)
requires(!IsChar<U> && sizeof(U) <= sizeof(u64))
: value { .as_unsigned = value }
, type { Type::UnsignedInteger }
{
}
template<Signed I>
explicit constexpr TypeErasedParameter(I const& value)
requires(!IsChar<I> && sizeof(I) <= sizeof(i64))
: value { .as_signed = value }
, type { Type::SignedInteger }
{
}
explicit constexpr TypeErasedParameter(bool const& value)
: value { .as_bool = value }
, type { Type::Boolean }
{
}
explicit constexpr TypeErasedParameter(char const& value)
: value { .as_char = value }
, type { Type::Character }
{
}
explicit constexpr TypeErasedParameter(float const& value)
: value { .as_float = value }
, type { Type::Float }
{
}
explicit constexpr TypeErasedParameter(double const& value)
: value { .as_double = value }
, type { Type::Double }
{
}
explicit constexpr TypeErasedParameter(StringView const& value)
: value { .as_string_view = value }
, type { Type::StringView }
{
}
explicit constexpr TypeErasedParameter(char const* value)
: value { .as_c_string = value }
, type { Type::CString }
{
}
template<typename T>
static consteval Type get_type()
explicit constexpr TypeErasedParameter(T const& value)
: value { .as_custom_type = { &value, __format_value<T> } }
, type { Type::CustomType }
{
if constexpr (IsIntegral<T>)
return get_type_from_size<sizeof(T), IsUnsigned<T>>();
else
return Type::Custom;
}
template<typename Visitor>
constexpr auto visit(Visitor&& visitor) const
{
switch (type) {
case TypeErasedParameter::Type::UInt8:
return visitor(*static_cast<u8 const*>(value));
case TypeErasedParameter::Type::UInt16:
return visitor(*static_cast<u16 const*>(value));
case TypeErasedParameter::Type::UInt32:
return visitor(*static_cast<u32 const*>(value));
case TypeErasedParameter::Type::UInt64:
return visitor(*static_cast<u64 const*>(value));
case TypeErasedParameter::Type::Int8:
return visitor(*static_cast<i8 const*>(value));
case TypeErasedParameter::Type::Int16:
return visitor(*static_cast<i16 const*>(value));
case TypeErasedParameter::Type::Int32:
return visitor(*static_cast<i32 const*>(value));
case TypeErasedParameter::Type::Int64:
return visitor(*static_cast<i64 const*>(value));
default:
TODO();
case Type::UnsignedInteger:
return visitor(value.as_unsigned);
case Type::SignedInteger:
return visitor(value.as_signed);
case Type::Boolean:
return visitor(value.as_bool);
case Type::Character:
return visitor(value.as_char);
case Type::Float:
return visitor(value.as_float);
case Type::Double:
return visitor(value.as_double);
case Type::StringView:
return visitor(value.as_string_view);
case Type::CString:
return visitor(value.as_c_string);
case Type::CustomType:
return visitor(value.as_custom_type);
}
VERIFY_NOT_REACHED();
}
constexpr size_t to_size() const
{
return visit([]<typename T>(T value) {
if constexpr (sizeof(T) > sizeof(size_t))
VERIFY(value < NumericLimits<size_t>::max());
if constexpr (IsSigned<T>)
return visit([]<typename T>(T value) -> size_t {
if constexpr (IsSame<T, u64>)
return static_cast<size_t>(value);
if constexpr (IsSame<T, i64>) {
VERIFY(value >= 0);
return static_cast<size_t>(value);
return static_cast<size_t>(value);
}
TODO();
});
}
// FIXME: Getters and setters.
void const* value;
union {
u64 as_unsigned;
i64 as_signed;
bool as_bool;
char as_char;
float as_float;
double as_double;
StringView as_string_view;
char const* as_c_string;
CustomType as_custom_type;
} value;
Type type;
ErrorOr<void> (*formatter)(TypeErasedFormatParams&, FormatBuilder&, FormatParser&, void const* value);
};
class FormatBuilder {
@ -293,15 +346,6 @@ private:
TypeErasedParameter m_parameters[0];
};
template<typename T>
ErrorOr<void> __format_value(TypeErasedFormatParams& params, FormatBuilder& builder, FormatParser& parser, void const* value)
{
Formatter<T> formatter;
formatter.parse(params, parser);
return formatter.format(builder, *static_cast<T const*>(value));
}
template<AllowDebugOnlyFormatters allow_debug_formatters, typename... Parameters>
class VariadicFormatParams : public TypeErasedFormatParams {
public:
@ -309,7 +353,7 @@ public:
explicit VariadicFormatParams(Parameters const&... parameters)
: TypeErasedFormatParams(sizeof...(Parameters))
, m_parameter_storage { TypeErasedParameter { &parameters, TypeErasedParameter::get_type<Parameters>(), __format_value<Parameters> }... }
, m_parameter_storage { TypeErasedParameter { parameters }... }
{
constexpr bool any_debug_formatters = (is_debug_only_formatter<Formatter<Parameters>>() || ...);
static_assert(!any_debug_formatters || allow_debug_formatters == AllowDebugOnlyFormatters::Yes,
@ -482,23 +526,9 @@ struct Formatter<char*> : Formatter<char const*> {
template<size_t Size>
struct Formatter<char[Size]> : Formatter<char const*> {
};
template<size_t Size>
struct Formatter<unsigned char[Size]> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, unsigned char const* value)
{
if (m_mode == Mode::Pointer) {
Formatter<FlatPtr> formatter { *this };
return formatter.format(builder, reinterpret_cast<FlatPtr>(value));
}
return Formatter<StringView>::format(builder, { value, Size });
}
};
template<>
struct Formatter<ByteString> : Formatter<StringView> {
};
template<>
struct Formatter<DeprecatedFlyString> : Formatter<StringView> {
};
template<typename T>
struct Formatter<T*> : StandardFormatter {
@ -517,8 +547,8 @@ struct Formatter<char> : StandardFormatter {
ErrorOr<void> format(FormatBuilder&, char);
};
template<>
struct Formatter<wchar_t> : StandardFormatter {
ErrorOr<void> format(FormatBuilder& builder, wchar_t);
struct Formatter<char32_t> : StandardFormatter {
ErrorOr<void> format(FormatBuilder& builder, char32_t);
};
template<>
struct Formatter<bool> : StandardFormatter {
@ -740,15 +770,10 @@ struct Formatter<FormatString> : Formatter<StringView> {
template<>
struct Formatter<Error> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, Error const& error)
{
if (error.is_syscall())
return Formatter<FormatString>::format(builder, "{}: {} (errno={})"sv, error.string_literal(), strerror(error.code()), error.code());
if (error.is_errno())
return Formatter<FormatString>::format(builder, "{} (errno={})"sv, strerror(error.code()), error.code());
ErrorOr<void> format(FormatBuilder& builder, Error const& error);
return Formatter<FormatString>::format(builder, "{}"sv, error.string_literal());
}
private:
ErrorOr<void> format_windows_error(FormatBuilder& builder, Error const& error);
};
template<typename T, typename ErrorType>

View File

@ -14,10 +14,12 @@
namespace AK {
namespace Detail {
template<size_t inline_capacity>
class ByteBuffer;
class StringData;
}
enum class TrailingCodePointTransformation : u8;
@ -25,12 +27,11 @@ enum class TrailingCodePointTransformation : u8;
class BigEndianInputBitStream;
class BigEndianOutputBitStream;
class Bitmap;
using ByteBuffer = Detail::ByteBuffer<32>;
class ByteString;
class ByteStringImpl;
class CircularBuffer;
class ConstrainedStream;
class CountingStream;
class DeprecatedFlyString;
class ByteString;
class Duration;
class Error;
class FlyString;
@ -49,7 +50,6 @@ class StackInfo;
class Stream;
class String;
class StringBuilder;
class StringImpl;
class StringView;
class UnixDateTime;
class Utf16View;
@ -58,6 +58,8 @@ class Utf32View;
class Utf8CodePointIterator;
class Utf8View;
using ByteBuffer = Detail::ByteBuffer<32>;
template<typename T>
class Span;
@ -161,7 +163,6 @@ using AK::CircularBuffer;
using AK::CircularQueue;
using AK::ConstrainedStream;
using AK::CountingStream;
using AK::DeprecatedFlyString;
using AK::DoublyLinkedList;
using AK::Error;
using AK::ErrorOr;
@ -193,7 +194,6 @@ using AK::StackInfo;
using AK::Stream;
using AK::String;
using AK::StringBuilder;
using AK::StringImpl;
using AK::StringView;
using AK::TrailingCodePointTransformation;
using AK::Traits;

View File

@ -2,6 +2,7 @@
* Copyright (C) 2016 Apple Inc. All rights reserved.
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
* Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -34,8 +35,15 @@
#include <AK/ScopeGuard.h>
#include <AK/Span.h>
#include <AK/StdLibExtras.h>
#include <AK/Swift.h>
#include <AK/TypeCasts.h>
#include <AK/Types.h>
// BlockRuntime methods for Objective-C block closure support.
extern "C" void* _Block_copy(void const*);
extern "C" void _Block_release(void const*);
extern "C" size_t Block_size(void const*);
namespace AK {
// These annotations are used to avoid capturing a variable with local storage in a lambda that outlives it
@ -48,6 +56,19 @@ namespace AK {
# define IGNORE_USE_IN_ESCAPING_LAMBDA
#endif
namespace Detail {
#ifdef AK_HAS_OBJC_ARC
inline constexpr bool HaveObjcArc = true;
#else
inline constexpr bool HaveObjcArc = false;
#endif
// validated in TestFunction.mm
inline constexpr size_t block_layout_size = 32;
}
template<typename>
class Function;
@ -84,7 +105,7 @@ public:
if (!m_size)
return {};
if (auto* wrapper = callable_wrapper())
return ReadonlyBytes { wrapper, m_size };
return ReadonlyBytes { wrapper->raw_callable(), m_size };
return {};
}
@ -102,6 +123,13 @@ public:
init_with_callable(move(f), CallableKind::FunctionPointer);
}
template<typename BlockType>
Function(BlockType b)
requires((IsBlockClosure<BlockType> && IsCallableWithArguments<BlockType, Out, In...>))
{
init_with_callable(move(b), CallableKind::Block);
}
Function(Function&& other)
{
move_from(move(other));
@ -141,6 +169,15 @@ public:
return *this;
}
template<typename BlockType>
Function& operator=(BlockType&& block)
requires((IsBlockClosure<BlockType> && IsCallableWithArguments<BlockType, Out, In...>))
{
clear();
init_with_callable(static_cast<RemoveCVReference<BlockType>>(block), CallableKind::Block);
return *this;
}
Function& operator=(nullptr_t)
{
clear();
@ -160,6 +197,7 @@ private:
enum class CallableKind {
FunctionPointer,
FunctionObject,
Block,
};
class CallableWrapperBase {
@ -167,8 +205,8 @@ private:
virtual ~CallableWrapperBase() = default;
// Note: This is not const to allow storing mutable lambdas.
virtual Out call(In...) = 0;
virtual void destroy() = 0;
virtual void init_and_swap(u8*, size_t) = 0;
virtual void const* raw_callable() const = 0;
};
template<typename CallableType>
@ -187,9 +225,14 @@ private:
return m_callable(forward<In>(in)...);
}
void destroy() final override
virtual ~CallableWrapper() final override
{
delete this;
if constexpr (IsBlockClosure<CallableType>) {
if constexpr (Detail::HaveObjcArc)
m_callable = nullptr;
else
_Block_release(m_callable);
}
}
// NOLINTNEXTLINE(readability-non-const-parameter) False positive; destination is used in a placement new expression
@ -199,6 +242,14 @@ private:
new (destination) CallableWrapper { move(m_callable) };
}
void const* raw_callable() const final override
{
if constexpr (IsBlockClosure<CallableType>)
return static_cast<u8 const*>(bridge_cast<void>(m_callable)) + Detail::block_layout_size;
else
return &m_callable;
}
private:
CallableType m_callable;
};
@ -207,6 +258,7 @@ private:
NullPointer,
Inline,
Outline,
Block,
};
CallableWrapperBase* callable_wrapper() const
@ -215,6 +267,7 @@ private:
case FunctionKind::NullPointer:
return nullptr;
case FunctionKind::Inline:
case FunctionKind::Block:
return bit_cast<CallableWrapperBase*>(&m_storage);
case FunctionKind::Outline:
return *bit_cast<CallableWrapperBase**>(&m_storage);
@ -234,12 +287,21 @@ private:
}
m_deferred_clear = false;
auto* wrapper = callable_wrapper();
if (m_kind == FunctionKind::Inline) {
switch (m_kind) {
case FunctionKind::Inline:
VERIFY(wrapper);
wrapper->~CallableWrapperBase();
} else if (m_kind == FunctionKind::Outline) {
break;
case FunctionKind::Outline:
VERIFY(wrapper);
wrapper->destroy();
delete wrapper;
break;
case FunctionKind::Block:
VERIFY(wrapper);
wrapper->~CallableWrapperBase();
break;
case FunctionKind::NullPointer:
break;
}
m_kind = FunctionKind::NullPointer;
}
@ -256,18 +318,33 @@ private:
}
VERIFY(m_call_nesting_level == 0);
using WrapperType = CallableWrapper<Callable>;
if (callable_kind == CallableKind::FunctionObject)
m_size = sizeof(Callable);
else
m_size = 0;
if constexpr (IsBlockClosure<Callable>) {
auto block_size = Block_size(bridge_cast<void>(callable));
VERIFY(block_size >= Detail::block_layout_size);
m_size = block_size - Detail::block_layout_size;
}
if constexpr (alignof(Callable) > inline_alignment || sizeof(WrapperType) > inline_capacity) {
*bit_cast<CallableWrapperBase**>(&m_storage) = new WrapperType(forward<Callable>(callable));
m_kind = FunctionKind::Outline;
} else {
static_assert(sizeof(WrapperType) <= inline_capacity);
new (m_storage) WrapperType(forward<Callable>(callable));
m_kind = FunctionKind::Inline;
if constexpr (IsBlockClosure<Callable>) {
if constexpr (Detail::HaveObjcArc) {
new (m_storage) WrapperType(forward<Callable>(callable));
} else {
new (m_storage) WrapperType(reinterpret_cast<Callable>(_Block_copy(callable)));
}
m_kind = FunctionKind::Block;
} else {
new (m_storage) WrapperType(forward<Callable>(callable));
m_kind = FunctionKind::Inline;
}
}
if (callable_kind == CallableKind::FunctionObject)
m_size = sizeof(WrapperType);
else
m_size = 0;
}
void move_from(Function&& other)
@ -279,8 +356,9 @@ private:
case FunctionKind::NullPointer:
break;
case FunctionKind::Inline:
case FunctionKind::Block:
other_wrapper->init_and_swap(m_storage, inline_capacity);
m_kind = FunctionKind::Inline;
m_kind = other.m_kind;
break;
case FunctionKind::Outline:
*bit_cast<CallableWrapperBase**>(&m_storage) = other_wrapper;
@ -302,7 +380,7 @@ private:
static constexpr size_t inline_capacity = 4 * sizeof(void*);
alignas(inline_alignment) u8 m_storage[inline_capacity];
};
} SWIFT_UNSAFE_REFERENCE;
}

View File

@ -13,6 +13,7 @@
#include <AK/Utf16View.h>
namespace AK {
// Consume a number of characters
StringView GenericLexer::consume(size_t count)
{

View File

@ -41,6 +41,12 @@ template<typename T, typename... Ts>
return (... || (forward<T>(to_compare) >= forward<Ts>(valid_values)));
}
template<typename T, typename... Ts>
[[nodiscard]] constexpr bool first_is_equal_to_all_of(T&& to_compare, Ts&&... valid_values)
{
return (... && (forward<T>(to_compare) == forward<Ts>(valid_values)));
}
template<typename T, typename... Ts>
[[nodiscard]] constexpr bool first_is_smaller_than_all_of(T&& to_compare, Ts&&... valid_values)
{
@ -64,9 +70,11 @@ template<typename T, typename... Ts>
{
return (... && (forward<T>(to_compare) >= forward<Ts>(valid_values)));
}
}
#if USING_AK_GLOBALLY
using AK::first_is_equal_to_all_of;
using AK::first_is_larger_or_equal_than_all_of;
using AK::first_is_larger_or_equal_than_one_of;
using AK::first_is_larger_than_all_of;

View File

@ -57,12 +57,12 @@ public:
void clear() { m_table.clear(); }
void clear_with_capacity() { m_table.clear_with_capacity(); }
HashSetResult set(K const& key, V const& value) { return m_table.set({ key, value }); }
HashSetResult set(K const& key, V&& value) { return m_table.set({ key, move(value) }); }
HashSetResult set(K&& key, V&& value) { return m_table.set({ move(key), move(value) }); }
ErrorOr<HashSetResult> try_set(K const& key, V const& value) { return m_table.try_set({ key, value }); }
ErrorOr<HashSetResult> try_set(K const& key, V&& value) { return m_table.try_set({ key, move(value) }); }
ErrorOr<HashSetResult> try_set(K&& key, V&& value) { return m_table.try_set({ move(key), move(value) }); }
HashSetResult set(K const& key, V const& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.set({ key, value }, existing_entry_behavior); }
HashSetResult set(K const& key, V&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.set({ key, move(value) }, existing_entry_behavior); }
HashSetResult set(K&& key, V&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.set({ move(key), move(value) }, existing_entry_behavior); }
ErrorOr<HashSetResult> try_set(K const& key, V const& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.try_set({ key, value }, existing_entry_behavior); }
ErrorOr<HashSetResult> try_set(K const& key, V&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.try_set({ key, move(value) }, existing_entry_behavior); }
ErrorOr<HashSetResult> try_set(K&& key, V&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace) { return m_table.try_set({ move(key), move(value) }, existing_entry_behavior); }
bool remove(K const& key)
{

View File

@ -789,10 +789,11 @@ private:
BucketType* m_buckets { nullptr };
[[no_unique_address]] CollectionDataType m_collection_data;
NO_UNIQUE_ADDRESS CollectionDataType m_collection_data;
size_t m_size { 0 };
size_t m_capacity { 0 };
};
}
#if USING_AK_GLOBALLY

View File

@ -15,18 +15,18 @@ namespace AK {
ErrorOr<ByteBuffer> decode_hex(StringView input)
{
if ((input.length() % 2) != 0)
return Error::from_string_view_or_print_error_and_return_errno("Hex string was not an even length"sv, EINVAL);
return Error::from_string_literal("Hex string was not an even length");
auto output = TRY(ByteBuffer::create_zeroed(input.length() / 2));
for (size_t i = 0; i < input.length() / 2; ++i) {
auto const c1 = decode_hex_digit(input[i * 2]);
if (c1 >= 16)
return Error::from_string_view_or_print_error_and_return_errno("Hex string contains invalid digit"sv, EINVAL);
return Error::from_string_literal("Hex string contains invalid digit");
auto const c2 = decode_hex_digit(input[i * 2 + 1]);
if (c2 >= 16)
return Error::from_string_view_or_print_error_and_return_errno("Hex string contains invalid digit"sv, EINVAL);
return Error::from_string_literal("Hex string contains invalid digit");
output[i] = (c1 << 4) + c2;
}

View File

@ -48,6 +48,7 @@ private:
HashTable<int> m_allocated_ids;
int m_minimum_value { 1 };
};
}
#if USING_AK_GLOBALLY

View File

@ -10,7 +10,6 @@
#include <AK/Endian.h>
#include <AK/Format.h>
#include <AK/Optional.h>
#include <AK/SipHash.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <AK/Vector.h>
@ -144,11 +143,6 @@ private:
static_assert(sizeof(IPv4Address) == 4);
template<>
struct Traits<IPv4Address> : public DefaultTraits<IPv4Address> {
static unsigned hash(IPv4Address const& address) { return secure_sip_hash(static_cast<u64>(address.to_u32())); }
};
template<>
struct Formatter<IPv4Address> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, IPv4Address value)

View File

@ -111,6 +111,18 @@ public:
if (string.is_null())
return {};
// NOTE: This supports URI syntax (square brackets) for IPv6 addresses.
// See: https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2
auto const starts_with_bracket = string.starts_with('[');
auto const ends_with_bracket = string.ends_with(']');
if (starts_with_bracket || ends_with_bracket) {
if (!starts_with_bracket || !ends_with_bracket)
return {};
string = string.substring_view(1, string.length() - 2);
}
auto const parts = string.split_view(':', SplitBehavior::KeepEmpty);
if (parts.is_empty())
return {};
@ -255,12 +267,6 @@ private:
static_assert(sizeof(IPv6Address) == 16);
template<>
struct Traits<IPv6Address> : public DefaultTraits<IPv6Address> {
// SipHash-4-8 is considered conservatively secure, even if not cryptographically secure.
static unsigned hash(IPv6Address const& address) { return sip_hash_bytes<4, 8>({ &address.to_in6_addr_t(), sizeof(address.to_in6_addr_t()) }); }
};
template<>
struct Formatter<IPv6Address> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, IPv6Address const& value)

View File

@ -85,4 +85,61 @@ constexpr T reinterpret_as_octal(T decimal)
return result;
}
template<Unsigned T>
constexpr T gcd(T x, T y)
{
if (x == 0)
return y;
if (y == 0)
return x;
int shift = 0;
while (((x | y) & 1) == 0) {
x >>= 1;
y >>= 1;
shift++;
}
while (x != y) {
if (x & 1) {
if (y & 1) {
if (x > y)
x -= y;
else
y -= x;
} else {
y >>= 1;
}
} else {
x >>= 1;
if (y & 1) {
if (x < y)
swap(x, y);
}
}
}
return x << shift;
}
template<Signed T>
constexpr T gcd(T x, T y)
{
return gcd(static_cast<MakeUnsigned<T>>(abs(x)), static_cast<MakeUnsigned<T>>(abs(y)));
}
template<Unsigned T>
constexpr T lcm(T x, T y)
{
if (x == 0 || y == 0)
return 0;
return x / gcd(x, y) * y;
}
template<Signed T>
constexpr T lcm(T x, T y)
{
return lcm(static_cast<MakeUnsigned<T>>(abs(x)), static_cast<MakeUnsigned<T>>(abs(y)));
}
}

View File

@ -169,7 +169,7 @@ private:
IntrusiveListStorage<T, Container>* m_storage = nullptr;
SubstitutedIntrusiveListNode<T, Container>* m_next = nullptr;
SubstitutedIntrusiveListNode<T, Container>* m_prev = nullptr;
[[no_unique_address]] SelfReferenceIfNeeded<Container, IsRaw> m_self;
NO_UNIQUE_ADDRESS SelfReferenceIfNeeded<Container, IsRaw> m_self;
};
template<class T, typename Container, SubstitutedIntrusiveListNode<T, Container> T::* member>

View File

@ -174,7 +174,14 @@ private:
static V* node_to_value(TreeNode& node)
{
#ifdef AK_OS_WINDOWS
// NOTE: https://learn.microsoft.com/en-us/cpp/build/reference/vmb-vmg-representation-method?view=msvc-170
static_assert(sizeof(member) == 4);
auto distance = bit_cast<u8*>(static_cast<FlatPtr>(bit_cast<u32>(member)));
return bit_cast<V*>(bit_cast<u8*>(&node) - distance);
#else
return bit_cast<V*>(bit_cast<u8*>(&node) - bit_cast<u8*>(member));
#endif
}
};
@ -205,7 +212,7 @@ private:
#endif
bool m_in_tree { false };
[[no_unique_address]] SelfReferenceIfNeeded<Container, IsRaw> m_self;
NO_UNIQUE_ADDRESS SelfReferenceIfNeeded<Container, IsRaw> m_self;
};
// Specialise IntrusiveRedBlackTree for NonnullRefPtr

30
AK/JsonArray.cpp Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonArray.h>
#include <AK/JsonArraySerializer.h>
#include <AK/StringBuilder.h>
namespace AK {
String JsonArray::serialized() const
{
StringBuilder builder;
serialize(builder);
return MUST(builder.to_string());
}
void JsonArray::serialize(StringBuilder& builder) const
{
auto serializer = MUST(JsonArraySerializer<>::try_create(builder));
for_each([&](auto const& value) {
MUST(serializer.add(value));
});
MUST(serializer.finish());
}
}

View File

@ -8,8 +8,8 @@
#include <AK/Concepts.h>
#include <AK/Error.h>
#include <AK/JsonArraySerializer.h>
#include <AK/JsonValue.h>
#include <AK/String.h>
#include <AK/Vector.h>
namespace AK {
@ -38,12 +38,19 @@ public:
}
template<IterableContainerOf<JsonValue> ContainerT>
JsonArray(ContainerT const& source)
JsonArray(ContainerT&& source)
{
for (auto& value : source)
m_values.append(move(value));
}
template<IterableContainerOf<JsonValue> ContainerT>
JsonArray(ContainerT const& source)
{
for (auto const& value : source)
m_values.append(value);
}
JsonArray& operator=(JsonArray const& other)
{
if (this != &other)
@ -72,13 +79,15 @@ public:
ErrorOr<void> append(JsonValue value) { return m_values.try_append(move(value)); }
void set(size_t index, JsonValue value) { m_values.at(index) = move(value); }
template<typename Builder>
typename Builder::OutputType serialized() const;
String serialized() const;
void serialize(StringBuilder&) const;
template<typename Builder>
void serialize(Builder&) const;
[[nodiscard]] ByteString to_byte_string() const { return serialized<StringBuilder>(); }
template<typename Callback>
void for_each(Callback callback)
{
for (auto& value : m_values)
callback(value);
}
template<typename Callback>
void for_each(Callback callback) const
@ -87,6 +96,14 @@ public:
callback(value);
}
template<FallibleFunction<JsonValue&> Callback>
ErrorOr<void, CallbackErrorType<Callback>> try_for_each(Callback&& callback)
{
for (auto& value : m_values)
TRY(callback(value));
return {};
}
template<FallibleFunction<JsonValue const&> Callback>
ErrorOr<void, CallbackErrorType<Callback>> try_for_each(Callback&& callback) const
{
@ -95,6 +112,7 @@ public:
return {};
}
[[nodiscard]] Vector<JsonValue>& values() { return m_values; }
[[nodiscard]] Vector<JsonValue> const& values() const { return m_values; }
void ensure_capacity(size_t capacity) { m_values.ensure_capacity(capacity); }
@ -104,22 +122,6 @@ private:
Vector<JsonValue> m_values;
};
template<typename Builder>
inline void JsonArray::serialize(Builder& builder) const
{
auto serializer = MUST(JsonArraySerializer<>::try_create(builder));
for_each([&](auto& value) { MUST(serializer.add(value)); });
MUST(serializer.finish());
}
template<typename Builder>
inline typename Builder::OutputType JsonArray::serialized() const
{
Builder builder;
serialize(builder);
return builder.to_byte_string();
}
}
#if USING_AK_GLOBALLY

View File

@ -6,7 +6,9 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "JsonObject.h"
#include <AK/JsonObject.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/StringBuilder.h>
namespace AK {
@ -47,6 +49,14 @@ bool JsonObject::is_empty() const
return m_members.is_empty();
}
Optional<JsonValue&> JsonObject::get(StringView key)
{
auto it = m_members.find(key);
if (it == m_members.end())
return {};
return it->value;
}
Optional<JsonValue const&> JsonObject::get(StringView key) const
{
auto it = m_members.find(key);
@ -108,11 +118,18 @@ Optional<bool> JsonObject::get_bool(StringView key) const
return {};
}
Optional<ByteString> JsonObject::get_byte_string(StringView key) const
Optional<String const&> JsonObject::get_string(StringView key) const
{
if (auto value = get(key); value.has_value() && value->is_string())
return value->as_string();
return {};
}
Optional<JsonObject&> JsonObject::get_object(StringView key)
{
auto maybe_value = get(key);
if (maybe_value.has_value() && maybe_value->is_string())
return maybe_value->as_string();
if (maybe_value.has_value() && maybe_value->is_object())
return maybe_value->as_object();
return {};
}
@ -124,6 +141,14 @@ Optional<JsonObject const&> JsonObject::get_object(StringView key) const
return {};
}
Optional<JsonArray&> JsonObject::get_array(StringView key)
{
auto maybe_value = get(key);
if (maybe_value.has_value() && maybe_value->is_array())
return maybe_value->as_array();
return {};
}
Optional<JsonArray const&> JsonObject::get_array(StringView key) const
{
auto maybe_value = get(key);
@ -237,9 +262,14 @@ bool JsonObject::has_object(StringView key) const
return value.has_value() && value->is_object();
}
void JsonObject::set(ByteString const& key, JsonValue value)
void JsonObject::set(String key, JsonValue value)
{
m_members.set(key, move(value));
m_members.set(move(key), move(value));
}
void JsonObject::set(StringView key, JsonValue value)
{
set(MUST(String::from_utf8(key)), move(value));
}
bool JsonObject::remove(StringView key)
@ -247,9 +277,21 @@ bool JsonObject::remove(StringView key)
return m_members.remove(key);
}
ByteString JsonObject::to_byte_string() const
String JsonObject::serialized() const
{
return serialized<StringBuilder>();
StringBuilder builder;
serialize(builder);
return MUST(builder.to_string());
}
void JsonObject::serialize(StringBuilder& builder) const
{
auto serializer = MUST(JsonObjectSerializer<>::try_create(builder));
for_each_member([&](auto& key, auto& value) {
MUST(serializer.add(key, value));
});
MUST(serializer.finish());
}
}

View File

@ -8,19 +8,18 @@
#pragma once
#include <AK/ByteString.h>
#include <AK/Concepts.h>
#include <AK/Error.h>
#include <AK/HashMap.h>
#include <AK/JsonArray.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonValue.h>
#include <AK/String.h>
namespace AK {
class JsonObject {
template<typename Callback>
using CallbackErrorType = decltype(declval<Callback>()(declval<ByteString const&>(), declval<JsonValue const&>()).release_error());
using CallbackErrorType = decltype(declval<Callback>()(declval<String const&>(), declval<JsonValue const&>()).release_error());
public:
JsonObject();
@ -52,6 +51,7 @@ public:
[[nodiscard]] bool has_array(StringView key) const;
[[nodiscard]] bool has_object(StringView key) const;
Optional<JsonValue&> get(StringView key);
Optional<JsonValue const&> get(StringView key) const;
template<Integral T>
@ -74,15 +74,19 @@ public:
Optional<FlatPtr> get_addr(StringView key) const;
Optional<bool> get_bool(StringView key) const;
Optional<ByteString> get_byte_string(StringView key) const;
Optional<String const&> get_string(StringView key) const;
Optional<JsonObject&> get_object(StringView key);
Optional<JsonObject const&> get_object(StringView key) const;
Optional<JsonArray&> get_array(StringView key);
Optional<JsonArray const&> get_array(StringView key) const;
Optional<double> get_double_with_precision_loss(StringView key) const;
Optional<float> get_float_with_precision_loss(StringView key) const;
void set(ByteString const& key, JsonValue value);
void set(String key, JsonValue value);
void set(StringView key, JsonValue value);
template<typename Callback>
void for_each_member(Callback callback) const
@ -91,7 +95,7 @@ public:
callback(member.key, member.value);
}
template<FallibleFunction<ByteString const&, JsonValue const&> Callback>
template<FallibleFunction<String const&, JsonValue const&> Callback>
ErrorOr<void, CallbackErrorType<Callback>> try_for_each_member(Callback&& callback) const
{
for (auto const& member : m_members)
@ -101,61 +105,13 @@ public:
bool remove(StringView key);
template<typename Builder>
typename Builder::OutputType serialized() const;
template<typename Builder>
void serialize(Builder&) const;
[[nodiscard]] ByteString to_byte_string() const;
String serialized() const;
void serialize(StringBuilder&) const;
private:
OrderedHashMap<ByteString, JsonValue> m_members;
OrderedHashMap<String, JsonValue> m_members;
};
template<typename Builder>
inline void JsonObject::serialize(Builder& builder) const
{
auto serializer = MUST(JsonObjectSerializer<>::try_create(builder));
for_each_member([&](auto& key, auto& value) {
MUST(serializer.add(key, value));
});
MUST(serializer.finish());
}
template<typename Builder>
inline typename Builder::OutputType JsonObject::serialized() const
{
Builder builder;
serialize(builder);
return builder.to_byte_string();
}
template<typename Builder>
inline void JsonValue::serialize(Builder& builder) const
{
m_value.visit(
[&](Empty const&) { builder.append("null"sv); },
[&](bool const& value) { builder.append(value ? "true"sv : "false"sv); },
[&](Arithmetic auto const& value) { builder.appendff("{}", value); },
[&](ByteString const& value) {
builder.append('\"');
builder.append_escaped_for_json(value.bytes());
builder.append('\"');
},
[&](auto const& array_or_object) {
array_or_object->serialize(builder);
});
}
template<typename Builder>
inline typename Builder::OutputType JsonValue::serialized() const
{
Builder builder;
serialize(builder);
return builder.to_byte_string();
}
}
#if USING_AK_GLOBALLY

View File

@ -57,7 +57,7 @@ public:
return {};
}
ErrorOr<void> add(StringView key, ByteString const& value)
ErrorOr<void> add(StringView key, String const& value)
{
TRY(begin_item(key));
if constexpr (IsLegacyBuilder<Builder>) {

View File

@ -18,6 +18,12 @@ constexpr bool is_space(int ch)
return ch == '\t' || ch == '\n' || ch == '\r' || ch == ' ';
}
ErrorOr<JsonValue> JsonParser::parse(StringView input)
{
JsonParser parser(input);
return parser.parse_json();
}
// ECMA-404 9 String
// Boils down to
// STRING = "\"" *("[^\"\\]" | "\\" ("[\"\\bfnrt]" | "u[0-9A-Za-z]{4}")) "\""
@ -335,7 +341,7 @@ ErrorOr<JsonValue> JsonParser::parse_helper()
return Error::from_string_literal("JsonParser: Unexpected character");
}
ErrorOr<JsonValue> JsonParser::parse()
ErrorOr<JsonValue> JsonParser::parse_json()
{
auto result = TRY(parse_helper());
ignore_while(is_space);

View File

@ -13,14 +13,15 @@ namespace AK {
class JsonParser : private GenericLexer {
public:
static ErrorOr<JsonValue> parse(StringView);
private:
explicit JsonParser(StringView input)
: GenericLexer(input)
{
}
ErrorOr<JsonValue> parse();
private:
ErrorOr<JsonValue> parse_json();
ErrorOr<JsonValue> parse_helper();
ErrorOr<ByteString> consume_and_unescape_string();

View File

@ -9,32 +9,21 @@
#include <AK/JsonObject.h>
#include <AK/JsonParser.h>
#include <AK/JsonValue.h>
#include <AK/StringBuilder.h>
#include <AK/StringView.h>
namespace AK {
namespace {
using JsonValueStorage = Variant<
Empty,
bool,
i64,
u64,
double,
ByteString,
NonnullOwnPtr<JsonArray>,
NonnullOwnPtr<JsonObject>>;
static ErrorOr<JsonValueStorage> clone(JsonValueStorage const& other)
static ErrorOr<JsonValue::Storage> clone(JsonValue::Storage const& other)
{
return other.visit(
[](NonnullOwnPtr<JsonArray> const& value) -> ErrorOr<JsonValueStorage> {
[](NonnullOwnPtr<JsonArray> const& value) -> ErrorOr<JsonValue::Storage> {
return TRY(try_make<JsonArray>(*value));
},
[](NonnullOwnPtr<JsonObject> const& value) -> ErrorOr<JsonValueStorage> {
[](NonnullOwnPtr<JsonObject> const& value) -> ErrorOr<JsonValue::Storage> {
return TRY(try_make<JsonObject>(*value));
},
[](auto const& value) -> ErrorOr<JsonValueStorage> { return JsonValueStorage(value); });
}
[](auto const& value) -> ErrorOr<JsonValue::Storage> { return JsonValue::Storage(value); });
}
JsonValue::JsonValue() = default;
@ -164,23 +153,18 @@ JsonValue::JsonValue(long long unsigned value)
{
}
JsonValue::JsonValue(char const* cstring)
: m_value(ByteString { cstring })
{
}
JsonValue::JsonValue(double value)
: m_value(double { value })
{
}
JsonValue::JsonValue(ByteString const& value)
: m_value(value)
{
}
JsonValue::JsonValue(String value)
: m_value(move(value))
{
}
JsonValue::JsonValue(StringView value)
: m_value(ByteString { value })
: m_value(MUST(String::from_utf8(value)))
{
}
@ -206,7 +190,31 @@ JsonValue::JsonValue(JsonArray&& value)
ErrorOr<JsonValue> JsonValue::from_string(StringView input)
{
return JsonParser(input).parse();
return JsonParser::parse(input);
}
String JsonValue::serialized() const
{
StringBuilder builder;
serialize(builder);
return MUST(builder.to_string());
}
void JsonValue::serialize(StringBuilder& builder) const
{
m_value.visit(
[&](Empty const&) { builder.append("null"sv); },
[&](bool const& value) { builder.append(value ? "true"sv : "false"sv); },
[&](Arithmetic auto const& value) { builder.appendff("{}", value); },
[&](String const& value) {
builder.append('\"');
builder.append_escaped_for_json(value.bytes());
builder.append('\"');
},
[&](auto const& array_or_object) {
array_or_object->serialize(builder);
});
}
}

View File

@ -7,11 +7,10 @@
#pragma once
#include <AK/ByteString.h>
#include <AK/Forward.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h>
#include <AK/OwnPtr.h>
#include <AK/StringBuilder.h>
#include <AK/String.h>
namespace AK {
@ -26,6 +25,16 @@ public:
Object,
};
using Storage = Variant<
Empty,
bool,
i64,
u64,
double,
String,
NonnullOwnPtr<JsonArray>,
NonnullOwnPtr<JsonObject>>;
static ErrorOr<JsonValue> from_string(StringView);
JsonValue();
@ -43,10 +52,9 @@ public:
JsonValue(long unsigned);
JsonValue(long long);
JsonValue(long long unsigned);
JsonValue(double);
JsonValue(char const*);
JsonValue(ByteString const&);
JsonValue(String);
JsonValue(StringView);
template<typename T>
@ -68,24 +76,8 @@ public:
JsonValue& operator=(JsonArray&&);
JsonValue& operator=(JsonObject&&);
template<typename Builder>
typename Builder::OutputType serialized() const;
template<typename Builder>
void serialize(Builder&) const;
ByteString as_string_or(ByteString const& alternative) const
{
if (is_string())
return as_string();
return alternative;
}
ByteString deprecated_to_byte_string() const
{
if (is_string())
return as_string();
return serialized<StringBuilder>();
}
String serialized() const;
void serialize(StringBuilder&) const;
Optional<int> get_int() const { return get_integer<int>(); }
Optional<i32> get_i32() const { return get_integer<i32>(); }
@ -124,9 +116,9 @@ public:
return m_value.get<bool>();
}
ByteString const& as_string() const
String const& as_string() const
{
return m_value.get<ByteString>();
return m_value.get<String>();
}
JsonObject& as_object()
@ -160,14 +152,14 @@ public:
[](Empty const&) { return Type::Null; },
[](bool const&) { return Type::Bool; },
[](Arithmetic auto const&) { return Type::Number; },
[](ByteString const&) { return Type::String; },
[](String const&) { return Type::String; },
[](NonnullOwnPtr<JsonArray> const&) { return Type::Array; },
[](NonnullOwnPtr<JsonObject> const&) { return Type::Object; });
}
bool is_null() const { return m_value.has<Empty>(); }
bool is_bool() const { return m_value.has<bool>(); }
bool is_string() const { return m_value.has<ByteString>(); }
bool is_string() const { return m_value.has<String>(); }
bool is_array() const { return m_value.has<NonnullOwnPtr<JsonArray>>(); }
bool is_object() const { return m_value.has<NonnullOwnPtr<JsonObject>>(); }
bool is_number() const
@ -222,23 +214,14 @@ public:
bool equals(JsonValue const& other) const;
private:
Variant<
Empty,
bool,
i64,
u64,
double,
ByteString,
NonnullOwnPtr<JsonArray>,
NonnullOwnPtr<JsonObject>>
m_value;
Storage m_value;
};
template<>
struct Formatter<JsonValue> : Formatter<StringView> {
ErrorOr<void> format(FormatBuilder& builder, JsonValue const& value)
{
return Formatter<StringView>::format(builder, value.serialized<StringBuilder>());
return Formatter<StringView>::format(builder, value.serialized());
}
};

View File

@ -35,6 +35,7 @@ template<FloatingPoint T>
constexpr T L2_E = 1.442695040888963407359924681001892137L;
namespace Details {
template<size_t>
constexpr size_t product_even();
template<>
@ -48,6 +49,7 @@ template<>
constexpr size_t product_odd<1>() { return 1; }
template<size_t value>
constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
}
template<FloatingPoint T>
@ -103,6 +105,7 @@ constexpr T fabs(T x)
}
namespace Rounding {
template<FloatingPoint T>
constexpr T ceil(T num)
{
@ -385,6 +388,7 @@ using Rounding::round_to;
using Rounding::trunc;
namespace Division {
template<FloatingPoint T>
constexpr T fmod(T x, T y)
{
@ -462,6 +466,7 @@ constexpr T remainder(T x, T y)
return __builtin_remainderf(x, y);
#endif
}
}
using Division::fmod;
@ -1036,6 +1041,7 @@ constexpr I clamp_to(T value)
#undef CONSTEXPR_STATE
#undef AARCH64_INSTRUCTION
}
#if USING_AK_GLOBALLY

View File

@ -15,6 +15,7 @@
namespace AK {
namespace Detail {
constexpr void const* bitap_bitwise(void const* haystack, size_t haystack_length, void const* needle, size_t needle_length)
{
VERIFY(needle_length < 32);
@ -40,6 +41,7 @@ constexpr void const* bitap_bitwise(void const* haystack, size_t haystack_length
return nullptr;
}
}
template<typename HaystackIterT>

View File

@ -10,32 +10,6 @@
#include <AK/Types.h>
#include <string.h>
ALWAYS_INLINE void fast_u32_copy(u32* dest, u32 const* src, size_t count)
{
#if ARCH(X86_64)
asm volatile(
"rep movsl\n"
: "+S"(src), "+D"(dest), "+c"(count)::"memory");
#else
__builtin_memcpy(dest, src, count * 4);
#endif
}
ALWAYS_INLINE void fast_u32_fill(u32* dest, u32 value, size_t count)
{
#if ARCH(X86_64)
asm volatile(
"rep stosl\n"
: "=D"(dest), "=c"(count)
: "D"(dest), "c"(count), "a"(value)
: "memory");
#else
for (auto* p = dest; p < (dest + count); ++p) {
*p = value;
}
#endif
}
namespace AK {
inline void secure_zero(void* ptr, size_t size)

View File

@ -58,7 +58,7 @@ ErrorOr<Bytes> FixedMemoryStream::read_some(Bytes bytes)
ErrorOr<void> FixedMemoryStream::read_until_filled(AK::Bytes bytes)
{
if (remaining() < bytes.size())
return Error::from_string_view_or_print_error_and_return_errno("Can't read past the end of the stream memory"sv, EINVAL);
return Error::from_string_literal("Can't read past the end of the stream memory");
m_bytes.slice(m_offset).copy_trimmed_to(bytes);
m_offset += bytes.size();
@ -71,19 +71,19 @@ ErrorOr<size_t> FixedMemoryStream::seek(i64 offset, SeekMode seek_mode)
switch (seek_mode) {
case SeekMode::SetPosition:
if (offset > static_cast<i64>(m_bytes.size()))
return Error::from_string_view_or_print_error_and_return_errno("Offset past the end of the stream memory"sv, EINVAL);
return Error::from_string_literal("Offset past the end of the stream memory");
m_offset = offset;
break;
case SeekMode::FromCurrentPosition:
if (offset + static_cast<i64>(m_offset) > static_cast<i64>(m_bytes.size()))
return Error::from_string_view_or_print_error_and_return_errno("Offset past the end of the stream memory"sv, EINVAL);
return Error::from_string_literal("Offset past the end of the stream memory");
m_offset += offset;
break;
case SeekMode::FromEndPosition:
if (-offset > static_cast<i64>(m_bytes.size()))
return Error::from_string_view_or_print_error_and_return_errno("Offset past the start of the stream memory"sv, EINVAL);
return Error::from_string_literal("Offset past the start of the stream memory");
m_offset = m_bytes.size() + offset;
break;
@ -108,7 +108,7 @@ ErrorOr<size_t> FixedMemoryStream::write_some(ReadonlyBytes bytes)
ErrorOr<void> FixedMemoryStream::write_until_depleted(ReadonlyBytes bytes)
{
if (remaining() < bytes.size())
return Error::from_string_view_or_print_error_and_return_errno("Write of entire buffer ends past the memory area"sv, EINVAL);
return Error::from_string_literal("Write of entire buffer ends past the memory area");
TRY(write_some(bytes));
return {};
@ -124,6 +124,22 @@ size_t FixedMemoryStream::remaining() const
return m_bytes.size() - m_offset;
}
void AllocatingMemoryStream::peek_some(Bytes bytes) const
{
size_t read_bytes = 0;
auto peek_offset = m_read_offset;
while (read_bytes < bytes.size()) {
auto range = MUST(next_read_range(peek_offset));
if (range.size() == 0)
break;
auto copied_bytes = range.copy_trimmed_to(bytes.slice(read_bytes));
read_bytes += copied_bytes;
peek_offset += copied_bytes;
}
}
ErrorOr<Bytes> AllocatingMemoryStream::read_some(Bytes bytes)
{
size_t read_bytes = 0;
@ -131,7 +147,7 @@ ErrorOr<Bytes> AllocatingMemoryStream::read_some(Bytes bytes)
while (read_bytes < bytes.size()) {
VERIFY(m_write_offset >= m_read_offset);
auto range = TRY(next_read_range());
auto range = TRY(next_read_range(m_read_offset));
if (range.size() == 0)
break;
@ -169,7 +185,7 @@ ErrorOr<void> AllocatingMemoryStream::discard(size_t count)
VERIFY(m_write_offset >= m_read_offset);
if (count > used_buffer_size())
return Error::from_string_view_or_print_error_and_return_errno("Number of discarded bytes is higher than the number of allocated bytes"sv, EINVAL);
return Error::from_string_literal("Number of discarded bytes is higher than the number of allocated bytes");
m_read_offset += count;
@ -231,13 +247,13 @@ ErrorOr<Optional<size_t>> AllocatingMemoryStream::offset_of(ReadonlyBytes needle
return AK::memmem(search_spans.begin(), search_spans.end(), needle);
}
ErrorOr<ReadonlyBytes> AllocatingMemoryStream::next_read_range()
ErrorOr<ReadonlyBytes> AllocatingMemoryStream::next_read_range(size_t read_offset) const
{
VERIFY(m_write_offset >= m_read_offset);
VERIFY(m_write_offset >= read_offset);
size_t const chunk_index = m_read_offset / CHUNK_SIZE;
size_t const chunk_offset = m_read_offset % CHUNK_SIZE;
size_t const read_size = min(CHUNK_SIZE - m_read_offset % CHUNK_SIZE, m_write_offset - m_read_offset);
size_t const chunk_index = read_offset / CHUNK_SIZE;
size_t const chunk_offset = read_offset % CHUNK_SIZE;
size_t const read_size = min(CHUNK_SIZE - read_offset % CHUNK_SIZE, m_write_offset - read_offset);
if (read_size == 0)
return ReadonlyBytes { static_cast<u8*>(nullptr), 0 };

View File

@ -50,7 +50,7 @@ public:
{
if constexpr (!IsConst<T>) {
if (!m_writing_enabled)
return Error::from_string_view_or_print_error_and_return_errno("Tried to obtain a non-const reference from a read-only FixedMemoryStream"sv, EINVAL);
return Error::from_string_literal("Tried to obtain a non-const reference from a read-only FixedMemoryStream");
}
T* value = reinterpret_cast<T*>(m_bytes.offset_pointer(m_offset));
@ -66,7 +66,7 @@ public:
{
if constexpr (!IsConst<T>) {
if (!m_writing_enabled)
return Error::from_string_view_or_print_error_and_return_errno("Tried to obtain a non-const span from a read-only FixedMemoryStream"sv, EINVAL);
return Error::from_string_literal("Tried to obtain a non-const span from a read-only FixedMemoryStream");
}
Span<T> span { reinterpret_cast<T*>(m_bytes.offset_pointer(m_offset)), count };
@ -86,6 +86,8 @@ class AllocatingMemoryStream final : public Stream {
public:
static constexpr size_t CHUNK_SIZE = 4096;
void peek_some(Bytes) const;
virtual ErrorOr<Bytes> read_some(Bytes) override;
virtual ErrorOr<size_t> write_some(ReadonlyBytes) override;
virtual ErrorOr<void> discard(size_t) override;
@ -101,7 +103,7 @@ private:
// Note: We set the inline buffer capacity to zero to make moving chunks as efficient as possible.
using Chunk = AK::Detail::ByteBuffer<0>;
ErrorOr<ReadonlyBytes> next_read_range();
ErrorOr<ReadonlyBytes> next_read_range(size_t read_offset) const;
ErrorOr<Bytes> next_write_range();
void cleanup_unused_chunks();

View File

@ -26,14 +26,14 @@ public: \
c(c const&) = default; \
c& operator=(c const&) = default
#define AK_MAKE_CONDITIONALLY_NONMOVABLE(c, ...) \
public: \
c(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
#define AK_MAKE_CONDITIONALLY_NONMOVABLE(c, ...) \
public: \
c(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c&&) \
requires(!((AK::Detail::IsMoveConstructible __VA_ARGS__) || (AK::Detail::IsMoveAssignable __VA_ARGS__)) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete
#define AK_MAKE_CONDITIONALLY_MOVABLE(c, T) \
@ -41,14 +41,14 @@ public: \
c(c&&) = default; \
c& operator=(c&&) = default
#define AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, ...) \
public: \
c(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
#define AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, ...) \
public: \
c(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c const&) \
requires(!((AK::Detail::IsCopyConstructible __VA_ARGS__) || (AK::Detail::IsCopyAssignable __VA_ARGS__)) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete
#define AK_MAKE_CONDITIONALLY_COPYABLE(c, ...) \

View File

@ -53,6 +53,7 @@ struct Traits<NonnullRawPtr<T>> : public DefaultTraits<NonnullRawPtr<T>> {
};
namespace Detail {
template<typename T>
inline constexpr bool IsHashCompatible<NonnullRawPtr<T>, T> = true;

View File

@ -46,16 +46,16 @@ public:
enum AdoptTag { Adopt };
ALWAYS_INLINE NonnullRefPtr(T const& object)
: m_ptr(const_cast<T*>(&object))
ALWAYS_INLINE NonnullRefPtr(T& object)
: m_ptr(&object)
{
m_ptr->ref();
}
template<typename U>
requires(IsConvertible<U*, T*>)
ALWAYS_INLINE NonnullRefPtr(U const& object)
: m_ptr(const_cast<T*>(static_cast<T const*>(&object)))
ALWAYS_INLINE NonnullRefPtr(U& object)
: m_ptr(static_cast<T*>(&object))
{
m_ptr->ref();
}
@ -78,7 +78,7 @@ public:
}
ALWAYS_INLINE NonnullRefPtr(NonnullRefPtr const& other)
: m_ptr(const_cast<T*>(other.ptr()))
: m_ptr(other.ptr())
{
m_ptr->ref();
}
@ -86,7 +86,7 @@ public:
template<typename U>
requires(IsConvertible<U*, T*>)
ALWAYS_INLINE NonnullRefPtr(NonnullRefPtr<U> const& other)
: m_ptr(const_cast<T*>(static_cast<T const*>(other.ptr())))
: m_ptr(static_cast<T*>(other.ptr()))
{
m_ptr->ref();
}
@ -144,7 +144,7 @@ public:
return *this;
}
NonnullRefPtr& operator=(T const& object)
NonnullRefPtr& operator=(T& object)
{
NonnullRefPtr tmp { object };
swap(tmp);
@ -212,7 +212,7 @@ private:
ALWAYS_INLINE RETURNS_NONNULL T* as_nonnull_ptr() const
{
VERIFY(m_ptr);
ASSERT(m_ptr);
return m_ptr;
}

View File

@ -17,6 +17,7 @@
namespace AK {
namespace Detail {
template<auto condition, typename T>
struct ConditionallyResultType;
@ -29,6 +30,7 @@ template<typename T>
struct ConditionallyResultType<false, T> {
using Type = T;
};
}
template<auto condition, typename T>
@ -46,7 +48,7 @@ template<typename>
class Optional;
struct OptionalNone {
explicit OptionalNone() = default;
explicit constexpr OptionalNone() = default;
};
template<typename T, typename Self = Optional<T>>
@ -55,24 +57,24 @@ public:
using ValueType = T;
template<SameAs<OptionalNone> V>
Self& operator=(V)
ALWAYS_INLINE constexpr Self& operator=(V)
{
static_cast<Self&>(*this).clear();
return static_cast<Self&>(*this);
}
[[nodiscard]] ALWAYS_INLINE T* ptr() &
[[nodiscard]] ALWAYS_INLINE constexpr T* ptr() &
{
return static_cast<Self&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T*>(&static_cast<Self&>(*this).value())) : nullptr;
}
[[nodiscard]] ALWAYS_INLINE T const* ptr() const&
[[nodiscard]] ALWAYS_INLINE constexpr T const* ptr() const&
{
return static_cast<Self const&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T const*>(&static_cast<Self const&>(*this).value())) : nullptr;
}
template<typename O = T, typename Fallback = O>
[[nodiscard]] ALWAYS_INLINE O value_or(Fallback const& fallback) const&
[[nodiscard]] ALWAYS_INLINE constexpr O value_or(Fallback const& fallback) const&
{
if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value();
@ -81,7 +83,7 @@ public:
template<typename O = T, typename Fallback = O>
requires(!IsLvalueReference<O> && !IsRvalueReference<O>)
[[nodiscard]] ALWAYS_INLINE O value_or(Fallback&& fallback) &&
[[nodiscard]] ALWAYS_INLINE constexpr O value_or(Fallback&& fallback) &&
{
if (static_cast<Self&>(*this).has_value())
return move(static_cast<Self&>(*this).value());
@ -89,7 +91,7 @@ public:
}
template<typename Callback, typename O = T>
[[nodiscard]] ALWAYS_INLINE O value_or_lazy_evaluated(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr O value_or_lazy_evaluated(Callback callback) const
{
if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value();
@ -97,7 +99,7 @@ public:
}
template<typename Callback, typename O = T>
[[nodiscard]] ALWAYS_INLINE Optional<O> value_or_lazy_evaluated_optional(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr Optional<O> value_or_lazy_evaluated_optional(Callback callback) const
{
if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value();
@ -105,7 +107,7 @@ public:
}
template<typename Callback, typename O = T>
[[nodiscard]] ALWAYS_INLINE ErrorOr<O> try_value_or_lazy_evaluated(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<O> try_value_or_lazy_evaluated(Callback callback) const
{
if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value();
@ -113,21 +115,21 @@ public:
}
template<typename Callback, typename O = T>
[[nodiscard]] ALWAYS_INLINE ErrorOr<Optional<O>> try_value_or_lazy_evaluated_optional(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<Optional<O>> try_value_or_lazy_evaluated_optional(Callback callback) const
{
if (static_cast<Self const&>(*this).has_value())
return static_cast<Self const&>(*this).value();
return TRY(callback());
}
[[nodiscard]] ALWAYS_INLINE T const& operator*() const { return static_cast<Self const&>(*this).value(); }
[[nodiscard]] ALWAYS_INLINE T& operator*() { return static_cast<Self&>(*this).value(); }
[[nodiscard]] ALWAYS_INLINE constexpr T const& operator*() const { return static_cast<Self const&>(*this).value(); }
[[nodiscard]] ALWAYS_INLINE constexpr T& operator*() { return static_cast<Self&>(*this).value(); }
ALWAYS_INLINE T const* operator->() const { return &static_cast<Self const&>(*this).value(); }
ALWAYS_INLINE T* operator->() { return &static_cast<Self&>(*this).value(); }
ALWAYS_INLINE constexpr T const* operator->() const { return &static_cast<Self const&>(*this).value(); }
ALWAYS_INLINE constexpr T* operator->() { return &static_cast<Self&>(*this).value(); }
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
{
if constexpr (IsErrorOr) {
if (static_cast<Self&>(*this).has_value())
@ -142,7 +144,7 @@ public:
}
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
{
if constexpr (IsErrorOr) {
if (static_cast<Self const&>(*this).has_value())
@ -167,94 +169,152 @@ requires(!IsLvalueReference<T>) class [[nodiscard]] Optional<T> : public Optiona
public:
using ValueType = T;
ALWAYS_INLINE Optional() = default;
ALWAYS_INLINE constexpr Optional()
{
construct_null_if_necessary();
}
template<SameAs<OptionalNone> V>
Optional(V) { }
ALWAYS_INLINE constexpr Optional(V)
{
construct_null_if_necessary();
}
template<SameAs<OptionalNone> V>
Optional& operator=(V)
ALWAYS_INLINE constexpr Optional& operator=(V)
{
clear();
return *this;
}
AK_MAKE_CONDITIONALLY_COPYABLE(Optional, <T>);
AK_MAKE_CONDITIONALLY_NONMOVABLE(Optional, <T>);
AK_MAKE_CONDITIONALLY_MOVABLE(Optional, <T>);
AK_MAKE_CONDITIONALLY_DESTRUCTIBLE(Optional, <T>);
ALWAYS_INLINE Optional(Optional const& other)
ALWAYS_INLINE constexpr Optional(Optional const& other)
requires(!IsTriviallyCopyConstructible<T>)
: m_has_value(other.m_has_value)
{
if (other.has_value())
new (&m_storage) T(other.value());
construct_at<RemoveConst<T>>(&m_storage, other.value());
else
construct_null_if_necessary();
}
ALWAYS_INLINE Optional(Optional&& other)
ALWAYS_INLINE constexpr Optional(Optional&& other)
requires(!IsTriviallyMoveConstructible<T>)
: m_has_value(other.m_has_value)
{
if (other.has_value())
new (&m_storage) T(other.release_value());
construct_at<RemoveConst<T>>(&m_storage, other.release_value());
else
construct_null_if_necessary();
}
template<typename U>
requires(IsConstructible<T, U const&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional> && (!IsLvalueReference<U> || IsTriviallyCopyConstructible<U>)) ALWAYS_INLINE explicit Optional(Optional<U> const& other)
requires(IsConstructible<T, U const&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional> && (!IsLvalueReference<U> || IsTriviallyCopyConstructible<U>)) ALWAYS_INLINE explicit constexpr Optional(Optional<U> const& other)
: m_has_value(other.has_value())
{
if (other.has_value())
new (&m_storage) T(other.value());
construct_at<RemoveConst<T>>(&m_storage, other.value());
else
construct_null_if_necessary();
}
template<typename U>
requires(IsConstructible<T, U &&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional> && (!IsLvalueReference<U> || IsTriviallyMoveConstructible<U>)) ALWAYS_INLINE explicit Optional(Optional<U>&& other)
requires(IsConstructible<T, U &&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional> && (!IsLvalueReference<U> || IsTriviallyMoveConstructible<U>)) ALWAYS_INLINE explicit constexpr Optional(Optional<U>&& other)
: m_has_value(other.has_value())
{
if (other.has_value())
new (&m_storage) T(other.release_value());
construct_at<RemoveConst<T>>(&m_storage, other.release_value());
else
construct_null_if_necessary();
}
template<typename U = T>
requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
ALWAYS_INLINE explicit(!IsConvertible<U&&, T>) Optional(U&& value)
ALWAYS_INLINE explicit(!IsConvertible<U&&, T>) constexpr Optional(U&& value)
requires(!IsSame<RemoveCVReference<U>, Optional<T>> && IsConstructible<T, U &&>)
: m_has_value(true)
{
new (&m_storage) T(forward<U>(value));
construct_at<RemoveConst<T>>(&m_storage, forward<U>(value));
}
ALWAYS_INLINE Optional& operator=(Optional const& other)
ALWAYS_INLINE constexpr Optional& operator=(Optional const& other)
requires(!IsTriviallyCopyConstructible<T> || !IsTriviallyDestructible<T>)
{
if (this != &other) {
clear();
m_has_value = other.m_has_value;
if (other.has_value()) {
new (&m_storage) T(other.value());
if (other.has_value())
construct_at<RemoveConst<T>>(&m_storage, other.value());
}
return *this;
}
Optional& operator=(Optional&& other)
requires(!IsMoveConstructible<T> || !IsDestructible<T>)
= delete;
// Note: This overload is optional. It exists purely to match the SerenityOS and `std::optional` behaviour.
// The only (observable) difference between this overload and the next one is that this one calls the move assignment operator when both `this` and `other` have a value.
// The other overload just unconditionally calls the move constructor.
ALWAYS_INLINE constexpr Optional& operator=(Optional&& other)
requires(IsMoveAssignable<T> && IsMoveConstructible<T> && (!IsTriviallyMoveAssignable<T> || !IsTriviallyMoveConstructible<T> || !IsTriviallyDestructible<T>))
{
if (this != &other) {
if (has_value() && other.has_value()) {
value() = other.release_value();
} else if (has_value()) {
value().~T();
m_has_value = false;
} else if (other.has_value()) {
m_has_value = true;
construct_at<RemoveConst<T>>(&m_storage, other.release_value());
}
}
return *this;
}
ALWAYS_INLINE Optional& operator=(Optional&& other)
// Allow for move constructible but non-move assignable types, such as those containing const or reference fields,
// Note: This overload can also handle move assignable types perfectly fine, but the behaviour would be slightly different.
ALWAYS_INLINE constexpr Optional& operator=(Optional&& other)
requires(!IsMoveAssignable<T> && IsMoveConstructible<T> && (!IsTriviallyMoveConstructible<T> || !IsTriviallyDestructible<T>))
{
if (this != &other) {
clear();
m_has_value = other.m_has_value;
if (other.has_value()) {
new (&m_storage) T(other.release_value());
}
if (other.has_value())
construct_at<RemoveConst<T>>(&m_storage, other.release_value());
}
return *this;
}
ALWAYS_INLINE ~Optional()
template<class U = T>
requires(!IsOneOfIgnoringCVReference<U, Optional<T>, OptionalNone> && !(IsSame<U, T> && IsScalar<U>))
// Note: We restrict this to `!IsScalar<U>` to prevent undesired overload resolution for `= {}`.
ALWAYS_INLINE constexpr Optional<T>& operator=(U&& value)
requires(IsConstructible<T, U &&>)
{
if constexpr (IsAssignable<AddLvalueReference<T>, AddRvalueReference<U>>) {
if (m_has_value)
m_storage = forward<U>(value);
else
construct_at<RemoveConst<T>>(&m_storage, forward<U>(value));
m_has_value = true;
} else {
emplace(forward<U>(value));
}
return *this;
}
ALWAYS_INLINE constexpr ~Optional()
requires(!IsTriviallyDestructible<T> && IsDestructible<T>)
{
clear();
}
ALWAYS_INLINE void clear()
ALWAYS_INLINE constexpr void clear()
{
if (m_has_value) {
value().~T();
@ -263,41 +323,41 @@ public:
}
template<typename... Parameters>
ALWAYS_INLINE void emplace(Parameters&&... parameters)
ALWAYS_INLINE constexpr void emplace(Parameters&&... parameters)
{
clear();
m_has_value = true;
new (&m_storage) T(forward<Parameters>(parameters)...);
construct_at<RemoveConst<T>>(&m_storage, forward<Parameters>(parameters)...);
}
template<typename Callable>
ALWAYS_INLINE void lazy_emplace(Callable callable)
ALWAYS_INLINE constexpr void lazy_emplace(Callable callable)
{
clear();
m_has_value = true;
new (&m_storage) T { callable() };
construct_at<RemoveConst<T>>(&m_storage, callable());
}
[[nodiscard]] ALWAYS_INLINE bool has_value() const { return m_has_value; }
[[nodiscard]] ALWAYS_INLINE constexpr bool has_value() const { return m_has_value; }
[[nodiscard]] ALWAYS_INLINE T& value() &
[[nodiscard]] ALWAYS_INLINE constexpr T& value() &
{
VERIFY(m_has_value);
return *__builtin_launder(reinterpret_cast<T*>(&m_storage));
return m_storage;
}
[[nodiscard]] ALWAYS_INLINE T const& value() const&
[[nodiscard]] ALWAYS_INLINE constexpr T const& value() const&
{
VERIFY(m_has_value);
return *__builtin_launder(reinterpret_cast<T const*>(&m_storage));
return m_storage;
}
[[nodiscard]] ALWAYS_INLINE T value() &&
[[nodiscard]] ALWAYS_INLINE constexpr T value() &&
{
return release_value();
}
[[nodiscard]] ALWAYS_INLINE T release_value()
[[nodiscard]] ALWAYS_INLINE constexpr T release_value()
{
VERIFY(m_has_value);
T released_value = move(value());
@ -307,7 +367,27 @@ public:
}
private:
alignas(T) u8 m_storage[sizeof(T)];
ALWAYS_INLINE constexpr void construct_null_if_necessary(bool should_construct = is_constant_evaluated())
{
// OPTIMIZATION: Only construct the `m_null` member when we are constant-evaluating.
// Otherwise, this generates an unnecessary zero-fill.
#if defined(AK_COMPILER_GCC)
// NOTE: GCCs -Wuninitialized warning ends up checking this as well.
should_construct = true;
#endif
if (should_construct)
construct_at(&m_null);
}
union {
// FIXME: GCC seems to have an issue with uninitialized unions and non trivial types,
// which forces us to have an equally sized trivial null member in the union
// to pseudo-initialize the union.
struct {
u8 _[sizeof(T)];
} m_null;
RemoveConst<T> m_storage;
};
bool m_has_value { false };
};
@ -325,46 +405,46 @@ requires(IsLvalueReference<T>) class [[nodiscard]] Optional<T> {
public:
using ValueType = T;
ALWAYS_INLINE Optional() = default;
ALWAYS_INLINE constexpr Optional() = default;
template<SameAs<OptionalNone> V>
Optional(V) { }
ALWAYS_INLINE constexpr Optional(V) { }
template<SameAs<OptionalNone> V>
Optional& operator=(V)
ALWAYS_INLINE constexpr Optional& operator=(V)
{
clear();
return *this;
}
template<typename U = T>
ALWAYS_INLINE Optional(U& value)
ALWAYS_INLINE constexpr Optional(U& value)
requires(CanBePlacedInOptional<U&>)
: m_pointer(&value)
{
}
ALWAYS_INLINE Optional(RemoveReference<T>& value)
ALWAYS_INLINE constexpr Optional(RemoveReference<T>& value)
: m_pointer(&value)
{
}
template<typename U>
ALWAYS_INLINE Optional(Optional<U>& other)
ALWAYS_INLINE constexpr Optional(Optional<U>& other)
requires(CanBePlacedInOptional<U>)
: m_pointer(other.ptr())
{
}
template<typename U>
ALWAYS_INLINE Optional(Optional<U> const& other)
ALWAYS_INLINE constexpr Optional(Optional<U> const& other)
requires(CanBePlacedInOptional<U const>)
: m_pointer(other.ptr())
{
}
template<typename U>
ALWAYS_INLINE Optional(Optional<U>&& other)
ALWAYS_INLINE constexpr Optional(Optional<U>&& other)
requires(CanBePlacedInOptional<U>)
: m_pointer(other.ptr())
{
@ -372,7 +452,7 @@ public:
}
template<typename U>
ALWAYS_INLINE Optional& operator=(Optional<U>& other)
ALWAYS_INLINE constexpr Optional& operator=(Optional<U>& other)
requires(CanBePlacedInOptional<U>)
{
m_pointer = other.ptr();
@ -380,7 +460,7 @@ public:
}
template<typename U>
ALWAYS_INLINE Optional& operator=(Optional<U> const& other)
ALWAYS_INLINE constexpr Optional& operator=(Optional<U> const& other)
requires(CanBePlacedInOptional<U const>)
{
m_pointer = other.ptr();
@ -388,7 +468,7 @@ public:
}
template<typename U>
ALWAYS_INLINE Optional& operator=(Optional<U>&& other)
ALWAYS_INLINE constexpr Optional& operator=(Optional<U>&& other)
requires(CanBePlacedInOptional<U> && IsLvalueReference<U>)
{
m_pointer = other.m_pointer;
@ -398,7 +478,7 @@ public:
template<typename U>
requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
ALWAYS_INLINE Optional& operator=(U& value)
ALWAYS_INLINE constexpr Optional& operator=(U& value)
requires(CanBePlacedInOptional<U>)
{
m_pointer = &value;
@ -412,12 +492,12 @@ public:
requires(CanBePlacedInOptional<U>)
= delete;
ALWAYS_INLINE void clear()
ALWAYS_INLINE constexpr void clear()
{
m_pointer = nullptr;
}
[[nodiscard]] ALWAYS_INLINE bool has_value() const { return m_pointer != nullptr; }
[[nodiscard]] ALWAYS_INLINE constexpr bool has_value() const { return m_pointer != nullptr; }
[[nodiscard]] ALWAYS_INLINE RemoveReference<T>* ptr()
{
@ -429,20 +509,20 @@ public:
return m_pointer;
}
[[nodiscard]] ALWAYS_INLINE T value()
[[nodiscard]] ALWAYS_INLINE constexpr T value()
{
VERIFY(m_pointer);
return *m_pointer;
}
[[nodiscard]] ALWAYS_INLINE AddConstToReferencedType<T> value() const
[[nodiscard]] ALWAYS_INLINE constexpr AddConstToReferencedType<T> value() const
{
VERIFY(m_pointer);
return *m_pointer;
}
template<typename U>
requires(IsBaseOf<RemoveCVReference<T>, U>) [[nodiscard]] ALWAYS_INLINE AddConstToReferencedType<T> value_or(U& fallback) const
requires(IsBaseOf<RemoveCVReference<T>, U>) [[nodiscard]] ALWAYS_INLINE constexpr AddConstToReferencedType<T> value_or(U& fallback) const
{
if (m_pointer)
return value();
@ -450,26 +530,26 @@ public:
}
// Note that this ends up copying the value.
[[nodiscard]] ALWAYS_INLINE RemoveCVReference<T> value_or(RemoveCVReference<T> fallback) const
[[nodiscard]] ALWAYS_INLINE constexpr RemoveCVReference<T> value_or(RemoveCVReference<T> fallback) const
{
if (m_pointer)
return value();
return fallback;
}
[[nodiscard]] ALWAYS_INLINE T release_value()
[[nodiscard]] ALWAYS_INLINE constexpr T release_value()
{
return *exchange(m_pointer, nullptr);
}
ALWAYS_INLINE AddConstToReferencedType<T> operator*() const { return value(); }
ALWAYS_INLINE T operator*() { return value(); }
ALWAYS_INLINE constexpr AddConstToReferencedType<T> operator*() const { return value(); }
ALWAYS_INLINE constexpr T operator*() { return value(); }
ALWAYS_INLINE RawPtr<AddConst<RemoveReference<T>>> operator->() const { return &value(); }
ALWAYS_INLINE RawPtr<RemoveReference<T>> operator->() { return &value(); }
// Conversion operators from Optional<T&> -> Optional<T>, implicit when T is trivially copyable.
ALWAYS_INLINE operator Optional<RemoveCVReference<T>>() const
ALWAYS_INLINE constexpr operator Optional<RemoveCVReference<T>>() const
requires(IsTriviallyCopyable<RemoveCVReference<T>>)
{
if (has_value())
@ -478,7 +558,7 @@ public:
}
// Conversion operators from Optional<T&> -> Optional<T>, explicit when T is not trivially copyable, since this is usually a mistake.
ALWAYS_INLINE explicit operator Optional<RemoveCVReference<T>>() const
ALWAYS_INLINE explicit constexpr operator Optional<RemoveCVReference<T>>() const
requires(!IsTriviallyCopyable<RemoveCVReference<T>>)
{
if (has_value())
@ -492,7 +572,7 @@ public:
}
template<typename Callback>
[[nodiscard]] ALWAYS_INLINE T value_or_lazy_evaluated(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr T value_or_lazy_evaluated(Callback callback) const
{
if (m_pointer != nullptr)
return value();
@ -500,7 +580,7 @@ public:
}
template<typename Callback>
[[nodiscard]] ALWAYS_INLINE Optional<T> value_or_lazy_evaluated_optional(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr Optional<T> value_or_lazy_evaluated_optional(Callback callback) const
{
if (m_pointer != nullptr)
return value();
@ -508,7 +588,7 @@ public:
}
template<typename Callback>
[[nodiscard]] ALWAYS_INLINE ErrorOr<T> try_value_or_lazy_evaluated(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<T> try_value_or_lazy_evaluated(Callback callback) const
{
if (m_pointer != nullptr)
return value();
@ -516,7 +596,7 @@ public:
}
template<typename Callback>
[[nodiscard]] ALWAYS_INLINE ErrorOr<Optional<T>> try_value_or_lazy_evaluated_optional(Callback callback) const
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<Optional<T>> try_value_or_lazy_evaluated_optional(Callback callback) const
{
if (m_pointer != nullptr)
return value();
@ -524,7 +604,7 @@ public:
}
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
{
if constexpr (IsErrorOr) {
if (m_pointer != nullptr)
@ -539,7 +619,7 @@ public:
}
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
{
if constexpr (IsErrorOr) {
if (m_pointer != nullptr)
@ -558,18 +638,24 @@ private:
};
template<typename T1, typename T2>
ALWAYS_INLINE bool operator==(Optional<T1> const& first, Optional<T2> const& second)
ALWAYS_INLINE constexpr bool operator==(Optional<T1> const& first, Optional<T2> const& second)
{
return first.has_value() == second.has_value()
&& (!first.has_value() || first.value() == second.value());
}
template<typename T1, typename T2>
ALWAYS_INLINE bool operator==(Optional<T1> const& first, T2 const& second)
ALWAYS_INLINE constexpr bool operator==(Optional<T1> const& first, T2 const& second)
{
return first.has_value() && first.value() == second;
}
template<typename T>
ALWAYS_INLINE constexpr bool operator==(Optional<T> const& first, OptionalNone)
{
return !first.has_value();
}
}
#if USING_AK_GLOBALLY

View File

@ -207,6 +207,7 @@ struct Formatter<OwnPtr<T>> : Formatter<T*> {
return Formatter<T*>::format(builder, value.ptr());
}
};
}
#if USING_AK_GLOBALLY

View File

@ -180,13 +180,6 @@
# define VALIDATE_IS_RISCV64() static_assert(false, "Trying to include riscv64 only header on non riscv64 platform");
#endif
// Apple Clang 14.0.3 (shipped in Xcode 14.3) has a bug that causes __builtin_subc{,l,ll}
// to incorrectly return whether a borrow occurred on AArch64. See our writeup for the Qemu
// issue also caused by it: https://gitlab.com/qemu-project/qemu/-/issues/1659#note_1408275831
#if ARCH(AARCH64) && defined(__apple_build_version__) && __clang_major__ == 14
# define AK_BUILTIN_SUBC_BROKEN
#endif
#ifdef ALWAYS_INLINE
# undef ALWAYS_INLINE
#endif
@ -247,6 +240,15 @@
# define DISALLOW(message) __attribute__((error(message)))
#endif
#ifdef NO_UNIQUE_ADDRESS
# undef NO_UNIQUE_ADDRESS
#endif
#if defined(AK_OS_WINDOWS)
# define NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#else
# define NO_UNIQUE_ADDRESS [[no_unique_address]]
#endif
// GCC doesn't have __has_feature but clang does
#ifndef __has_feature
# define __has_feature(...) 0
@ -265,6 +267,14 @@
# define LSAN_UNREGISTER_ROOT_REGION(base, size)
#endif
#if __has_feature(blocks)
# define AK_HAS_BLOCKS
#endif
#if __has_feature(objc_arc)
# define AK_HAS_OBJC_ARC
#endif
#ifndef AK_OS_SERENITY
# ifdef AK_OS_WINDOWS
// FIXME: No idea where to get this, but it's 4096 anyway :^)

View File

@ -4,12 +4,67 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Platform.h>
#include <AK/Random.h>
#include <AK/UFixedBigInt.h>
#include <AK/UFixedBigIntDivision.h>
#if defined(AK_OS_WINDOWS)
# include <AK/NumericLimits.h>
# include <AK/Windows.h>
# include <bcrypt.h>
# include <ntstatus.h>
#endif
namespace AK {
// NOTE: This function is supposed to always give a random number. If possible it is of good quality, but it can fall
// back to rand() if it fails on some systems. For high speed you should probably use a different generator.
// See MathObject::random() from LibJS. Where cryptographic security is needed use LibCrypto/SecureRandom.h.
void fill_with_random([[maybe_unused]] Bytes bytes)
{
#if defined(AK_OS_SERENITY) || defined(AK_OS_ANDROID) || defined(AK_OS_BSD_GENERIC) || defined(AK_OS_HAIKU) || AK_LIBC_GLIBC_PREREQ(2, 36)
arc4random_buf(bytes.data(), bytes.size());
#elif defined(OSS_FUZZ)
#else
auto fill_with_random_fallback = [&]() {
for (auto& byte : bytes)
byte = rand();
};
# if defined(__unix__)
// The maximum permitted value for the getentropy length argument.
static constexpr size_t getentropy_length_limit = 256;
auto iterations = bytes.size() / getentropy_length_limit;
for (size_t i = 0; i < iterations; ++i) {
if (getentropy(bytes.data(), getentropy_length_limit) != 0) {
fill_with_random_fallback();
return;
}
bytes = bytes.slice(getentropy_length_limit);
}
if (bytes.is_empty() || getentropy(bytes.data(), bytes.size()) == 0)
return;
# elif defined(AK_OS_WINDOWS)
if (bytes.size() > NumericLimits<u32>::max()) [[unlikely]] {
fill_with_random_fallback();
return;
}
// NOTE: This is more secure than needed. But on modern hardware it be should more than fast enough.
NTSTATUS result = ::BCryptGenRandom(NULL, bytes.data(), bytes.size(), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (result == STATUS_SUCCESS)
return;
# endif
fill_with_random_fallback();
#endif
}
u32 get_random_uniform(u32 max_bounds)
{
// If we try to divide all 2**32 numbers into groups of "max_bounds" numbers, we may end up

View File

@ -18,38 +18,7 @@
namespace AK {
inline void fill_with_random([[maybe_unused]] Bytes bytes)
{
#if defined(AK_OS_SERENITY) || defined(AK_OS_ANDROID) || defined(AK_OS_BSD_GENERIC) || defined(AK_OS_HAIKU) || AK_LIBC_GLIBC_PREREQ(2, 36)
arc4random_buf(bytes.data(), bytes.size());
#elif defined(OSS_FUZZ)
#else
auto fill_with_random_fallback = [&]() {
for (auto& byte : bytes)
byte = rand();
};
# if defined(__unix__)
// The maximum permitted value for the getentropy length argument.
static constexpr size_t getentropy_length_limit = 256;
auto iterations = bytes.size() / getentropy_length_limit;
for (size_t i = 0; i < iterations; ++i) {
if (getentropy(bytes.data(), getentropy_length_limit) != 0) {
fill_with_random_fallback();
return;
}
bytes = bytes.slice(getentropy_length_limit);
}
if (bytes.is_empty() || getentropy(bytes.data(), bytes.size()) == 0)
return;
# endif
fill_with_random_fallback();
#endif
}
void fill_with_random([[maybe_unused]] Bytes bytes);
template<typename T>
inline T get_random()

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Platform.h>
namespace AK {
enum class RecursionDecision {
Recurse,
Continue,
Break,
};
}
#if USING_AK_GLOBALLY
using AK::RecursionDecision;
#endif

View File

@ -34,14 +34,14 @@ public:
};
RefPtr() = default;
RefPtr(T const* ptr)
: m_ptr(const_cast<T*>(ptr))
RefPtr(T* ptr)
: m_ptr(ptr)
{
ref_if_not_null(m_ptr);
}
RefPtr(T const& object)
: m_ptr(const_cast<T*>(&object))
RefPtr(T& object)
: m_ptr(&object)
{
m_ptr->ref();
}
@ -57,7 +57,7 @@ public:
}
ALWAYS_INLINE RefPtr(NonnullRefPtr<T> const& other)
: m_ptr(const_cast<T*>(other.ptr()))
: m_ptr(other.ptr())
{
m_ptr->ref();
}
@ -65,7 +65,7 @@ public:
template<typename U>
requires(IsConvertible<U*, T*>)
ALWAYS_INLINE RefPtr(NonnullRefPtr<U> const& other)
: m_ptr(const_cast<T*>(static_cast<T const*>(other.ptr())))
: m_ptr(static_cast<T*>(other.ptr()))
{
m_ptr->ref();
}
@ -93,7 +93,7 @@ public:
template<typename U>
RefPtr(RefPtr<U> const& other)
requires(IsConvertible<U*, T*>)
: m_ptr(const_cast<T*>(static_cast<T const*>(other.ptr())))
: m_ptr(static_cast<T*>(other.ptr()))
{
ref_if_not_null(m_ptr);
}
@ -180,14 +180,14 @@ public:
return *this;
}
ALWAYS_INLINE RefPtr& operator=(T const* ptr)
ALWAYS_INLINE RefPtr& operator=(T* ptr)
{
RefPtr tmp { ptr };
swap(tmp);
return *this;
}
ALWAYS_INLINE RefPtr& operator=(T const& object)
ALWAYS_INLINE RefPtr& operator=(T& object)
{
RefPtr tmp { object };
swap(tmp);
@ -303,13 +303,31 @@ struct Traits<RefPtr<T>> : public DefaultTraits<RefPtr<T>> {
template<typename T, typename U>
inline NonnullRefPtr<T> static_ptr_cast(NonnullRefPtr<U> const& ptr)
{
return NonnullRefPtr<T>(static_cast<T const&>(*ptr));
return NonnullRefPtr<T>(static_cast<T&>(*ptr));
}
template<typename T, typename U>
inline RefPtr<T> static_ptr_cast(RefPtr<U> const& ptr)
{
return RefPtr<T>(static_cast<T const*>(ptr.ptr()));
return RefPtr<T>(static_cast<T*>(ptr.ptr()));
}
template<typename T>
inline NonnullRefPtr<T> fixme_launder_const_through_pointer_cast(NonnullRefPtr<T const> const& ptr)
{
return NonnullRefPtr<T>(const_cast<T&>(*ptr));
}
template<typename T>
inline RefPtr<T> fixme_launder_const_through_pointer_cast(RefPtr<T const> const& ptr)
{
return RefPtr<T>(const_cast<T*>(ptr.ptr()));
}
template<typename T>
inline NonnullRefPtr<T> fixme_launder_const_through_pointer_cast(T const& ptr)
{
return NonnullRefPtr<T>(const_cast<T&>(ptr));
}
template<typename T, typename U>

View File

@ -81,6 +81,7 @@ static_assert(vector_length<i8x4> == 4);
static_assert(vector_length<f32x4> == 4);
namespace Detail {
template<typename T>
struct IndexVectorFor;
@ -113,4 +114,5 @@ static_assert(IsSame<IndexVectorFor<u64x4>, u64x4>);
static_assert(IsSame<IndexVectorFor<f32x4>, u32x4>);
static_assert(IsSame<IndexVectorFor<f64x4>, u64x4>);
#endif
}

View File

@ -185,6 +185,7 @@ ALWAYS_INLINE static void store4_masked(VectorType v, UnderlyingType* a, Underly
// Shuffle
namespace Detail {
template<SIMDVector T, SIMDVector Control, size_t... Idx>
ALWAYS_INLINE static T shuffle_impl(T a, Control control, IndexSequence<Idx...>)
{

View File

@ -12,6 +12,7 @@
#include <AK/StringBuilder.h>
namespace AK {
template<bool = true>
class ScopeLogger {
public:

View File

@ -300,6 +300,7 @@ private:
Node* m_tail { nullptr };
TSizeCalculationPolicy m_size_policy {};
};
}
#if USING_AK_GLOBALLY

View File

@ -1,176 +0,0 @@
/*
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteReader.h>
#include <AK/Random.h>
#include <AK/Singleton.h>
#include <AK/SipHash.h>
#include <AK/Span.h>
#include <AK/UFixedBigInt.h>
namespace AK {
ALWAYS_INLINE constexpr u64 rotate_left(u64 x, u64 bits)
{
return static_cast<u64>(((x) << (bits)) | ((x) >> (64 - (bits))));
}
ALWAYS_INLINE constexpr void sipround(u64& v0, u64& v1, u64& v2, u64& v3)
{
v0 += v1;
v1 = rotate_left(v1, 13);
v1 ^= v0;
v0 = rotate_left(v0, 32);
v2 += v3;
v3 = rotate_left(v3, 16);
v3 ^= v2;
v0 += v3;
v3 = rotate_left(v3, 21);
v3 ^= v0;
v2 += v1;
v1 = rotate_left(v1, 17);
v1 ^= v2;
v2 = rotate_left(v2, 32);
}
// Can handle u64 or u128 output as per reference implementation.
// We currenly only use u64 and further fold it to u32 (unsigned) for use in Traits.
template<size_t message_block_rounds, size_t finalization_rounds>
static void do_siphash(ReadonlyBytes input, u128 key, Bytes output)
{
VERIFY((output.size() == 8) || (output.size() == 16));
u64 v0 = 0x736f6d6570736575ull;
u64 v1 = 0x646f72616e646f6dull;
u64 v2 = 0x6c7967656e657261ull;
u64 v3 = 0x7465646279746573ull;
u64 const length = input.size();
auto const left = length & 7;
// The end of 64-bit blocks.
auto const block_end = length - (length % sizeof(u64));
u64 b = length << 56;
v3 ^= key.high();
v2 ^= key.low();
v1 ^= key.high();
v0 ^= key.low();
if (output.size() == 16)
v1 ^= 0xee;
for (size_t input_index = 0; input_index < block_end; input_index += 8) {
u64 const m = bit_cast<LittleEndian<u64>>(ByteReader::load64(input.slice(input_index, sizeof(u64)).data()));
v3 ^= m;
for (size_t i = 0; i < message_block_rounds; ++i)
sipround(v0, v1, v2, v3);
v0 ^= m;
}
switch (left) {
case 7:
b |= (static_cast<u64>(input[block_end + 6])) << 48;
[[fallthrough]];
case 6:
b |= (static_cast<u64>(input[block_end + 5])) << 40;
[[fallthrough]];
case 5:
b |= (static_cast<u64>(input[block_end + 4])) << 32;
[[fallthrough]];
case 4:
b |= (static_cast<u64>(input[block_end + 3])) << 24;
[[fallthrough]];
case 3:
b |= (static_cast<u64>(input[block_end + 2])) << 16;
[[fallthrough]];
case 2:
b |= (static_cast<u64>(input[block_end + 1])) << 8;
[[fallthrough]];
case 1:
b |= (static_cast<u64>(input[block_end + 0]));
break;
case 0:
break;
}
v3 ^= b;
for (size_t i = 0; i < message_block_rounds; ++i)
sipround(v0, v1, v2, v3);
v0 ^= b;
if (output.size() == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
for (size_t i = 0; i < finalization_rounds; ++i)
sipround(v0, v1, v2, v3);
b = v0 ^ v1 ^ v2 ^ v3;
LittleEndian<u64> b_le { b };
output.overwrite(0, &b_le, sizeof(b_le));
if (output.size() == 8)
return;
v1 ^= 0xdd;
for (size_t i = 0; i < finalization_rounds; ++i)
sipround(v0, v1, v2, v3);
b = v0 ^ v1 ^ v2 ^ v3;
b_le = b;
output.overwrite(sizeof(b_le), &b_le, sizeof(b_le));
}
struct SipHashKey {
SipHashKey()
{
// get_random is assumed to be secure, otherwise SipHash doesn't deliver on its promises!
key = get_random<u128>();
}
constexpr u128 operator*() const { return key; }
u128 key;
};
// Using a singleton is a little heavier than a plain static, but avoids an initialization order fiasco.
static Singleton<SipHashKey> static_sip_hash_key;
template<size_t message_block_rounds, size_t finalization_rounds>
unsigned sip_hash_u64(u64 input)
{
ReadonlyBytes input_bytes { &input, sizeof(input) };
u64 const output_u64 = sip_hash_bytes<message_block_rounds, finalization_rounds>(input_bytes);
return static_cast<unsigned>(output_u64 ^ (output_u64 >> 32));
}
unsigned standard_sip_hash(u64 input)
{
return sip_hash_u64<1, 3>(input);
}
unsigned secure_sip_hash(u64 input)
{
return sip_hash_u64<4, 8>(input);
}
template<size_t message_block_rounds, size_t finalization_rounds>
u64 sip_hash_bytes(ReadonlyBytes input)
{
auto sip_hash_key = **static_sip_hash_key;
u64 output = 0;
Bytes output_bytes { &output, sizeof(output) };
do_siphash<message_block_rounds, finalization_rounds>(input, sip_hash_key, output_bytes);
return output;
}
// Instantiate all used SipHash variants here:
template u64 sip_hash_bytes<1, 3>(ReadonlyBytes);
template u64 sip_hash_bytes<4, 8>(ReadonlyBytes);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
namespace AK {
// Ported from the SipHash reference implementation, released to the public domain:
// https://github.com/veorq/SipHash/blob/eee7d0d84dc7731df2359b243aa5e75d85f6eaef/siphash.c
// The standard is SipHash-2-4, but we use 1-3 for a little more speed.
// Cryptography should use 4-8 for (relative) conservative security,
// though SipHash itself is NOT a cryptographically secure hash algorithm.
template<size_t message_block_rounds, size_t finalization_rounds>
u64 sip_hash_bytes(ReadonlyBytes input);
unsigned standard_sip_hash(u64 input);
unsigned secure_sip_hash(u64 input);
}
#ifdef USING_AK_GLOBALLY
using AK::secure_sip_hash;
using AK::sip_hash_bytes;
using AK::standard_sip_hash;
#endif

View File

@ -186,8 +186,8 @@ public:
ALWAYS_INLINE constexpr void overwrite(size_t offset, void const* data, size_t data_size)
{
// make sure we're not told to write past the end
VERIFY(offset + data_size <= size());
__builtin_memmove(this->data() + offset, data, data_size);
VERIFY(offset + data_size <= size() * sizeof(T));
TypedTransfer<T>::copy(this->data() + offset, static_cast<T const*>(data), data_size / sizeof(T));
}
ALWAYS_INLINE constexpr size_t copy_to(Span<RemoveConst<T>> other) const
@ -306,6 +306,28 @@ public:
{
return { data(), size() };
}
template<typename TUnaryPredicate>
Optional<T&> last_matching(TUnaryPredicate const& predicate)
{
for (ssize_t i = size() - 1; i >= 0; --i) {
if (predicate(at(i))) {
return at(i);
}
}
return {};
}
template<typename TUnaryPredicate>
Optional<T&> first_matching(TUnaryPredicate const& predicate)
{
for (size_t i = 0; i < size(); ++i) {
if (predicate(at(i))) {
return at(i);
}
}
return {};
}
};
template<typename T>

Some files were not shown because too many files have changed in this diff Show More