Commit graph

76114 commits

Author SHA1 Message Date
Tim Ledbetter
8dd3c20436 AK: Add IsTriviallyRelocatable type trait 2026-03-19 14:21:44 +01:00
Tim Ledbetter
c173a66754 LibWeb: Avoid style computation if document is detached 2026-03-19 14:17:46 +01:00
Tim Ledbetter
26389363ad LibGfx+LibWeb: Move Skia backend context to process level singleton
Previously, this was attached to the traversable navigable. Using a
singleton instead allows us to use the context for detached documents.
2026-03-19 13:35:16 +01:00
mikiubo
d4cf537d58 LibCrypto: Implement KMAC authentication support
Add a LibCrypto::Authentication::KMAC helper over OpenSSL.
Add keygen/import/export logic into WebCrypto.
Register KMAC128/KMAC256 operations with SubtleCrypto.
2026-03-19 10:46:49 +01:00
mikiubo
6cc575b8a9 LibWeb: Import KMAC WPT tests 2026-03-19 10:46:49 +01:00
Callum Law
915fc4602b LibWeb: Implement CSS inherit() function
The remaining failing imported tests are due to wider issues which are
covered by FIXMEs (both existing and added in this commit)
2026-03-19 10:25:37 +01:00
Andrew Kaster
f06bd0303f LibJS: Use enum for retrieving well known symbols from C++ to Rust 2026-03-19 09:48:32 +01:00
Andrew Kaster
5d43707896 LibJS: Directly use LiteralValueKind enum across FFI boundary 2026-03-19 09:48:32 +01:00
Shannon Booth
27436c3971 LibWeb/HTML: Do not run script on child removal
Matching the behaviour of the other big three browser engines,
also tested by WPT, but does not appear to be explicitly specified.

I also noticed when investigating that browser engines disagree
about whether a child mutation should trigger script execution.
For this, I've just gone with the behaviour of Webkit/Chromium of
not running script.
2026-03-19 09:46:54 +01:00
Shannon Booth
cc6536b527 LibWeb/HTML: Always provide ChildrenChangedMetadata to children changed 2026-03-19 09:46:54 +01:00
Timothy Flynn
02783a6f1d LibIPC: Disable unused LocalSocket notifier in TransportSocket
TransportSocket uses its own pipe-based notification mechanism on the IO
thread, making LocalSocket's built-in Core::Notifier redundant. When the
socket reaches EOF, this notifier is disabled from the IO thread. Since
the QSocketNotifier lives on the main thread, the its destruction is
deferred. If the socket is closed before the deferred destruction runs,
Qt detects the invalid socket on the next poll and prints:

    QSocketNotifier: Invalid socket 50 and type 'Read', disabling...

Fix this by disabling the redundant socket-level notifier upfront in the
TransportSocket constructor.
2026-03-19 09:44:22 +01:00
Andreas Kling
3efd1a1bb5 LibJS: Reject duplicate params across destructuring patterns in C++
The C++ parser was not rejecting duplicate parameter names across
destructuring patterns in non-simple parameter lists. For example,
`function f({ bar, ...a }, { bar, ...b }) {}` was accepted despite
being a syntax error per spec.

The existing inline duplicate check only ran for identifier parameters,
missing the case where both parameters are binding patterns. Add a
post-parse pass that collects all bound names and checks for duplicates
when the parameter list is non-simple (or in strict mode/arrows).

Also fix existing tests that relied on the incorrect behavior and add
new test coverage for destructuring duplicate detection.
2026-03-19 09:43:11 +01:00
Andreas Kling
1a03421897 LibTest: Count parse failures in test-js suite statistics
When a test file failed to parse, the error was printed but never
counted in the suite pass/fail statistics. This happened because
run_file_test() returned early on parse errors before reaching the
code that increments m_counts.suites_failed and m_counts.files_total.

This meant a test suite could have parse failures that were silently
invisible in the final "Test Suites: N passed, N total" summary.
2026-03-19 09:43:11 +01:00
Andreas Kling
2a93576915 LibWeb: Store ImageData.data as own property for IC friendliness
The IDL-generated getter for ImageData.data lives on ImageDataPrototype,
which means every access goes through a getter call that cannot be
cached by the GetById inline cache.

By also storing the Uint8ClampedArray as an own data property directly
on each ImageData instance, the prototype getter is shadowed and
GetById can cache the access like any other data property. This matches
the approach used by WebKit and is compatible with web expectations.
2026-03-19 09:42:04 +01:00
Andreas Kling
1ff61754a7 LibJS: Re-box double arithmetic results as Int32 when possible
When the asmint computes a double result for Add, Sub, Mul,
Math.floor, Math.ceil, or Math.sqrt, try to store it as Int32
if the value is a whole number in [INT32_MIN, INT32_MAX] and
not -0.0. This mirrors the JS::Value(double) constructor and
allows downstream int32 fast paths to fire.

Also add label uniquification to the DSL macro expander so the
same macro can be used multiple times in one handler without
label collisions.
2026-03-19 09:42:04 +01:00
Andreas Kling
5e403af5be LibJS: Tighten asmint ToInt32 boxing
Teach js_to_int32 to leave a clean low 32-bit result on success, then
use box_int32_clean in the ToInt32 fast path and adjacent boolean
coercions. This removes one instruction from the AArch64 fjcvtzs path
and trims the boolean boxing path without changing behavior.
2026-03-19 09:42:04 +01:00
Andreas Kling
645f481825 LibJS: Fast-path Float32Array indexed access
Add the small AsmIntGen float32 load, store, and conversion operations
needed to handle Float32Array directly in the AsmInt typed-array
GetByValue and PutByValue paths.

This covers direct indexed reads plus both int32 and double stores,
and adds regression coverage for Math.fround rounding, negative zero,
and NaN.
2026-03-19 09:42:04 +01:00
Andreas Kling
6614971e6f LibJS: Fast-path Uint8ClampedArray indexed access
Teach the asm typed-array GetByValue and PutByValue paths to handle
Uint8ClampedArray directly. Reads can share the Uint8Array load path,
while int32 stores clamp in asm instead of bailing out to C++.

Add a direct indexed access regression test for clamped int32 stores.
2026-03-19 09:42:04 +01:00
RubenKelevra
ba4b4c47dc LibJS: Route canParseSource through Script::parse and add parser modes 2026-03-18 17:41:36 -05:00
RubenKelevra
fae2f8f3ba LibJS: Align new-expression paren flags with C++ parser 2026-03-18 17:41:36 -05:00
RubenKelevra
3cb636ca38 LibJS: Keep new call-paren optional chaining valid 2026-03-18 17:41:36 -05:00
RubenKelevra
ea8fa63e79 LibJS: Reject optional chaining on unparenthesized new 2026-03-18 17:41:36 -05:00
RubenKelevra
04b27429de LibJS: Isolate super validity in nested function scopes 2026-03-18 17:41:36 -05:00
RubenKelevra
d8469c384d LibJS: Reject invalid bare private identifier usage 2026-03-18 17:41:36 -05:00
RubenKelevra
d6229a1cc8 LibJS: Fix async arrow and for-of async parsing 2026-03-18 17:41:36 -05:00
RubenKelevra
af777b5d86 LibJS: Align duplicate parameter early errors 2026-03-18 17:41:36 -05:00
RubenKelevra
40984d0f39 LibJS: Enforce const initializers in declarations 2026-03-18 17:41:36 -05:00
Timothy Flynn
7e3bb9d984 UI/Qt: Replace QTabWidget with a custom TabWidget composition
QTabWidget's built-in tab bar management made it difficult to properly
position the new tab button, and caused visual artifacts with the
separator line across themes.

Replace QTabWidget with a custom TabWidget that places a QTabBar
alongside an explicit new tab button. This us gives full control over
the tab bar row layout.
2026-03-18 18:39:53 -04:00
Timothy Flynn
7b78d3786e UI/AppKit: Set an initial intrinsic size for the location search field
We initially create the search field with no frame or size constraints.
The causes AppKit to log verbose warnings at start up. Here, we set an
intrinsic size initially, which becomes overridden once the window has
an actual size.
2026-03-18 18:04:01 -04:00
Andreas Kling
9299d430c8 LibJS: Cache typed array data pointers for indexed access
Cache raw data pointers on fixed-length typed array views so asm
GetByValue and PutByValue can use them directly for indexed
element access.

Replace the asm typed-array hot-path
ArrayBuffer/DataBlock/ByteBuffer walk with one cached_data_ptr load.
Remove six unconditional loads, four branches, and the byte_offset
add before the element access, trading them for one
cached_data_ptr null check.

Keep direct C++ typed-array access on IsValidIntegerIndex-based
checks, invalidate cached pointers eagerly when a backing
ArrayBuffer is detached, and add regression coverage for shrink,
regrow, and detach on number and BigInt typed arrays.
2026-03-18 13:59:05 -05:00
Jelle Raaijmakers
cf050288fa Tests/LibWeb: Test performance with relative timing rather than absolute
The flaky test `input-value-does-not-force-layout.html` had an absolute
threshold of 5000ms before it would fail, which did not work that great
on CI. Since we are dealing with wildly different performance
characteristics on our CI runners (and ASAN enabled), make this test
perform relative timing comparisons instead.

Confirmed to still fail locally with the original fix removed.
2026-03-18 13:53:42 -05:00
Callum Law
0019836fc1 LibWeb: Support more gradient color spaces
Skia has added support for these so it's trivial for us to as well
2026-03-18 13:21:57 +00:00
Callum Law
2300ba41fb LibWeb: Use generic <color-interpolation-method> parsing for color-mix
This also fixes an issue where we would allow arbitrary idents as color
spaces
2026-03-18 13:21:57 +00:00
Callum Law
9db607b1a7 LibWeb: Use generic <color-interpolation-method> parsing for gradients
See previous commit for details

We now support parsing of `display-p3-linear` (although it just falls
back to using Oklab since Skia doesn't support it)
2026-03-18 13:21:57 +00:00
Callum Law
d8c38a294c LibWeb: Add a generic <color-interpolation-method> parsing method
Previously we had two implementations for parsing
`<color-interpolation-method>`, one for gradients and one for
`color-mix()` - this commit adds another which will unify the existing
ones in following commits.

This implementation has a couple of advantages over the existing ones:
 - It is simpler in that it uses global CSS enums and their helper
   functions
 - It is spec compliant (unlike the `color-mix()` one which allows
   arbitrary idents)
 - It parses as a `StyleValue` which will be required once we support
   `<custom-color-space>` since that can be an `ident()` which isn't
   resolvable at parse time
2026-03-18 13:21:57 +00:00
Andrew Kaster
125c89f9e5 LibUnicode: Apply workspace clippy lints to Rust code
Follow-up to 94d3aa8d89
2026-03-18 08:36:13 -04:00
Andrew Kaster
6b1a346fad LibUnicode: Generate FFI bindings with cbindgen
This places the exported structs and functions in the Unicode::FFI
namespace.
2026-03-18 08:36:13 -04:00
Andreas Kling
b4185f0ecd LibJS: Split packed and holey asm indexed fast paths
Use dedicated Packed branches in GetByValue and PutByValue so
in-bounds indexed accesses can skip hole checks and slot
reloads.

Keep Holey writes on the guarded arm, and keep append writes on
the C++ slow path so PutByValue still respects non-extensible
indexed objects and arrays with a non-writable length.

Add a bytecode regression that exercises both append failure
cases through the real js binary path.
2026-03-17 22:28:35 -05:00
Andreas Kling
5f586ae406 LibJS: Promote Holey arrays to Packed when all holes are filled
Arrays created via new Array(N) or by setting .length start as Holey
since their elements are not present. After sequential fill (e.g.
for (i=0; i<N; i++) a[i]=v), all holes are filled but the array
remained Holey, preventing the Packed fast paths in the asm
interpreter from triggering.

Now, whenever indexed_put() writes to the last index of a Holey
array, we scan for remaining holes and promote to Packed if none
are found. Only checking on writes to the last index avoids O(N^2)
scanning on partial fills while still catching the common
sequential fill pattern.
2026-03-17 22:28:35 -05:00
Andreas Kling
5895cacc21 LibJS: Add Array.prototype fast paths for packed arrays
When the receiver is an Array with packed storage and an intact default
prototype chain, some methods can skip the generic property access
machinery and operate directly on the indexed element storage.

This patch adds fast paths for push(), pop(), concat(), slice() and
splice().
2026-03-17 22:28:35 -05:00
Andreas Kling
614713ed08 LibJS: Replace IndexedProperties with inline Packed/Holey/Dictionary
Replace the OwnPtr<IndexedPropertyStorage> indirection with inline
indexed element storage directly on Object. This eliminates virtual
dispatch and reduces indirection for indexed property access.

The new system uses three storage kinds tracked by IndexedStorageKind:

- Packed: Dense array, no holes. Elements stored in a malloced Value*
  array with capacity header (same layout as named properties).
- Holey: Dense array with possible holes marked by empty sentinel.
  Same physical layout as Packed.
- Dictionary: Sparse storage using GenericIndexedPropertyStorage,
  type-punned into the m_indexed_elements pointer.

Transitions: None->Packed->Holey->Dictionary (mostly monotonic).
Dictionary mode triggers on non-default attributes or sparse arrays.

Object keeps the same 48-byte size since m_indexed_elements (8 bytes)
replaces IndexedProperties (8 bytes), and the storage kind + array
size fit in existing padding alongside m_flags.

The asm interpreter benefits from one fewer indirection: it now reads
the element pointer and array size directly from Object fields instead
of chasing through OwnPtr -> IndexedPropertyStorage -> Vector.

Removes: IndexedProperties, SimpleIndexedPropertyStorage,
IndexedPropertyStorage, IndexedPropertyIterator.
Keeps: GenericIndexedPropertyStorage (for Dictionary mode).
2026-03-17 22:28:35 -05:00
Andreas Kling
f574ef528d LibJS: Replace Vector<Value> with Value* for named property storage
Replace the 24-byte Vector<Value> m_storage with an 8-byte raw
Value* m_named_properties pointer, backed by a malloc'd allocation
with an inline capacity header.

Memory layout of the allocation:
  [u32 capacity] [u32 padding] [Value 0] [Value 1] ...
  m_named_properties points to Value 0.

This shrinks JS::Object from 64 to 48 bytes (on non-Windows
platforms) and removes one level of indirection for property access
in the asm interpreter, since the data pointer is now stored directly
on the object rather than inside a Vector's internal metadata.

Growth policy: max(4, max(needed, old_capacity * 2)).
2026-03-17 22:28:35 -05:00
Zaggy1024
15af5fb420 Tests: Consider video autoplay succeeded when it is not paused on load
Fixes a 1 in 200ish flake on autoplay-of-file-video-from-file-document.
2026-03-17 21:36:53 -05:00
Andrew Kaster
92e4c20ad5 LibJS: Generate FFI header using cbindgen instead of hand-rolling
Replace the BytecodeFactory header with cbindgen.

This will help ensure that types and enums and constants are kept in
sync between the C++ and Rust code. It's also a step in exporting more
Rust enums directly rather than relying on magic constants for
switch statements.

The FFI functions are now all placed in the JS::FFI namespace, which
is the cause for all the churn in the scripting parts of LibJS and
LibWeb.
2026-03-17 20:49:50 -05:00
Andrew Kaster
c381cd7d68 CMake: Pass cargo a path for dumping generated headers from build.rs 2026-03-17 20:49:50 -05:00
Andrew Kaster
ba8a71152c LibJS: Wrap ParseErrorCallback typedef in Option
The automatic conversion of `Option<function pointer>` to a C function
pointer is only supported by cbindgen if the option is in the typedef
itself, rather than an argument type. This no-op commit will make a
future cbingen update happy.
2026-03-17 20:49:50 -05:00
Zaggy1024
2e54c18fb3 LibWeb: Use a queue to process fullscreen request completions
Instead of immediately firing fullscreenchange, defer that until
WebContent's client has confirmed that it is in fullscreen for the
content. The fullscreenchange is fired by the viewport change, so in
cases where the fullscreen transition is instantaneous (i.e. the
fullscreen state is entered at the exact moment the viewport expands),
the resize event should precede the fullscreenchange event, as the spec
requires.

This fixes the WPT element-request-fullscreen-timing.html test, which
was previously succeeding by accident because we were immediately
fullscreenchange upon requestFullscreen() being called, instead of
following spec and doing the viewport (window) resize in parallel. The
WPT test was actually initially intended to assert that the
fullscreenchange event follows the resize event, but the WPT runner
didn't actually have a different resolution for normal vs fullscreen
viewports, so the resize event doesn't actually fire in their setup. In
our headless mode, the default viewport is 800x600, and the fullscreen
viewport is 1920x1080, so we do fire a resize event when entering
fullscreen. Therefore, that imported test is reverted to assert that
the resize precedes the fullscreenchange.
2026-03-17 18:58:37 -05:00
Zaggy1024
ae9537a53c AK: Use deducing this for AK::queue::head() and tail()
This allows us to grab these as mutable.
2026-03-17 18:58:37 -05:00
Zaggy1024
ac69815740 Everywhere: Add an is_fullscreen parameter to set_viewport
This will be used by the UIs to notify WebContent when fullscreen for
content is entered or exited.
2026-03-17 18:58:37 -05:00
Zaggy1024
1ceb012100 UI/AppKit: Don't call fully_exit_fullscreen() if WebContent initiated
This is a no-op on the WebContent side if it asked the UI to exit
fullscreen.
2026-03-17 18:58:37 -05:00