Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
aa280e3
LibWeb: Add a Rust-owned style value data representation
awesomekling Jul 17, 2026
f1ac1ea
LibSandbox: Allow utimensat() in the filesystem write seccomp group
awesomekling Jul 17, 2026
b1c97c8
LibWeb: Store KeywordStyleValue's data in a Rust-owned allocation
awesomekling Jul 17, 2026
3e713c9
LibWeb: Store number and integer style values in Rust-owned data
awesomekling Jul 17, 2026
0f6f976
LibWeb: Store dimension style values in Rust-owned data
awesomekling Jul 17, 2026
f4ed719
LibWeb: Store ratio style values in Rust-owned data
awesomekling Jul 17, 2026
f86a5ec
LibWeb: Store unicode-range, opacity and edge values in Rust-owned data
awesomekling Jul 17, 2026
08b7027
LibWeb: Store ten more style value types in Rust-owned data
awesomekling Jul 17, 2026
c305db6
LibWeb: Store string and custom-ident values in Rust-owned data
awesomekling Jul 17, 2026
1e1e397
LibWeb: Store six more style value types in Rust-owned data
awesomekling Jul 17, 2026
999a698
LibWeb: Store background, border-image and anchor values in Rust data
awesomekling Jul 17, 2026
4261607
LibWeb: Store position, shadow, content and counter values in Rust data
awesomekling Jul 17, 2026
7258e3e
LibWeb: Store four more style value types in Rust-owned data
awesomekling Jul 17, 2026
f91a2ef
LibWeb: Store style value lists in Rust-owned data
awesomekling Jul 17, 2026
f86c366
LibWeb: Store tuple, transformation and shorthand values in Rust data
awesomekling Jul 17, 2026
d91a403
LibWeb: Store display values in Rust-owned data
awesomekling Jul 17, 2026
9aee55c
LibWeb: Store radial size values in Rust-owned data
awesomekling Jul 17, 2026
2a7f98c
LibWeb: Store url() style values in Rust-owned data
awesomekling Jul 17, 2026
2656346
LibWeb: Store font source values in Rust-owned data
awesomekling Jul 17, 2026
99e3c94
LibWeb: Store color-scheme and unresolved values in Rust-owned data
awesomekling Jul 17, 2026
0f53438
LibWeb: Store counter definitions and grid placements in Rust data
awesomekling Jul 17, 2026
262e3d5
LibWeb: Store counter style values in Rust-owned data
awesomekling Jul 17, 2026
55837dc
LibWeb: Store cursor values in Rust-owned data
awesomekling Jul 17, 2026
aa2fa7a
LibWeb: Store the color style value base data in Rust
awesomekling Jul 17, 2026
96bdf0f
LibWeb: Store color function values in Rust-owned data
awesomekling Jul 17, 2026
1019c9a
LibWeb: Store color-mix values in Rust-owned data
awesomekling Jul 17, 2026
da72c4a
LibWeb: Store image-set values in Rust-owned data
awesomekling Jul 17, 2026
8904f23
LibWeb: Store linear gradient values in Rust-owned data
awesomekling Jul 17, 2026
6ab6674
LibWeb: Store conic and radial gradient values in Rust-owned data
awesomekling Jul 17, 2026
3b02077
LibWeb: Store grid-template-areas values in Rust-owned data
awesomekling Jul 17, 2026
67329d9
LibWeb: Store easing values in Rust-owned data
awesomekling Jul 17, 2026
ed9cdf9
LibWeb: Store grid track size lists in Rust-owned data
awesomekling Jul 17, 2026
72e863b
LibWeb: Store basic shape values in Rust-owned data
awesomekling Jul 17, 2026
66146e0
LibWeb: Store calculated values in Rust-owned data
awesomekling Jul 17, 2026
053c4eb
LibWeb: Store image values in Rust-owned data
awesomekling Jul 17, 2026
09c0641
LibWeb: Compare radial size components by value
awesomekling Jul 17, 2026
f330e1b
LibWeb: Update style value comments now that the conversion is done
awesomekling Jul 17, 2026
9cbca93
LibWeb: Share the style value pointer list marshalling helper
awesomekling Jul 17, 2026
19e52e1
LibWeb: Generate retained list impls in Rust with a macro
awesomekling Jul 17, 2026
856283a
LibWeb: Hoist the Rust value handle into the StyleValue base class
awesomekling Jul 17, 2026
821f252
LibWeb: Store border-radius and filter values in Rust-owned data
awesomekling Jul 17, 2026
2e49150
LibWeb: Merge the color base data into the color variant payloads
awesomekling Jul 17, 2026
1598924
LibWeb: Materialize easing and basic shape data eagerly
awesomekling Jul 18, 2026
7656cf0
LibWeb: Dispatch four style value operations by type tag
awesomekling Jul 18, 2026
32ce3b2
LibWeb: Dispatch is_computationally_independent by type tag
awesomekling Jul 18, 2026
ee8bb37
LibWeb: Dispatch serialize by type tag
awesomekling Jul 18, 2026
710bc58
LibWeb: Dispatch equals by type tag
awesomekling Jul 18, 2026
fd04ecc
LibWeb: Dispatch absolutized by type tag
awesomekling Jul 18, 2026
aaabc0b
LibWeb: Dispatch the color and iteration helpers by type tag
awesomekling Jul 18, 2026
988d7ab
LibWeb: Intern keyword, small integer and common number style values
awesomekling Jul 18, 2026
9f1a6cb
LibWeb: Intern small pixel lengths and common percentage values
awesomekling Jul 18, 2026
9151764
LibWeb: Skip inset reconstruction when no inset value is calculated
awesomekling Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions AK/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,31 @@ class String : public Detail::StringBase {
[[nodiscard]] static String from_utf8_without_validation(ReadonlyBytes);
[[nodiscard]] static String from_ascii_without_validation(ReadonlyBytes);

// NB: These round-trip the one-word raw representation through FFI bridges (e.g. the LibWeb
// Rust style value data), which retain the raw value and manage its reference manually.
// to_raw_leaked() leaks one reference to the bridge, from_raw() reconstructs a string
// without consuming the bridge's reference, and unref_raw() releases it.
[[nodiscard]] FlatPtr to_raw_leaked() const
{
if (!is_short_string())
data_without_union_member_assertion()->ref();
return raw({});
}

[[nodiscard]] static String from_raw(FlatPtr raw)
{
auto string = adopt_raw(raw);
if (!string.is_short_string())
string.data_without_union_member_assertion()->ref();
return string;
}

static void unref_raw(FlatPtr raw)
{
// Adopt the bridge's reference and let it drop.
auto string = adopt_raw(raw);
}

[[nodiscard]] static constexpr String from_ascii_short_string_without_validation(char const* data, size_t length)
{
VERIFY(length <= Detail::MAX_SHORT_STRING_BYTE_COUNT);
Expand Down Expand Up @@ -231,6 +256,16 @@ class String : public Detail::StringBase {

using ShortString = Detail::ShortString;

// Adopts a raw value previously produced by to_raw_leaked(), together with ownership of one
// reference to its data if it is not a short string.
[[nodiscard]] static String adopt_raw(FlatPtr raw)
{
String string;
auto const** data = __builtin_launder(&string.m_impl.data);
*data = bit_cast<Detail::StringData const*>(raw);
return string;
}

constexpr bool is_invalid() const
{
return raw(Badge<String> {}) == 0;
Expand Down
28 changes: 28 additions & 0 deletions AK/Utf16FlyString.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,34 @@ class [[nodiscard]] Utf16FlyString {

static Utf16FlyString from_utf16(Utf16View const&);

// NB: These round-trip the one-word raw representation through FFI bridges (e.g. the LibWeb
// Rust style value data), which retain the raw value and manage its reference manually.
// to_raw_leaked() leaks one reference to the bridge, from_raw() reconstructs a fly string
// without consuming the bridge's reference, and unref_raw() releases it.
[[nodiscard]] FlatPtr to_raw_leaked() const
{
if (m_data.has_long_storage())
m_data.data({})->ref();
return m_data.raw({});
}

[[nodiscard]] static Utf16FlyString from_raw(FlatPtr raw)
{
auto base = Detail::Utf16StringBase::adopt_raw({}, raw);
if (base.has_long_storage())
base.data({})->ref();

Utf16FlyString string;
string.m_data = move(base);
return string;
}

static void unref_raw(FlatPtr raw)
{
// Adopt the bridge's reference and let it drop.
auto base = Detail::Utf16StringBase::adopt_raw({}, raw);
}

template<typename T>
requires(IsOneOf<RemoveCVReference<T>, Utf16String, Utf16FlyString>)
static Utf16FlyString from_utf16(T&&) = delete;
Expand Down
20 changes: 20 additions & 0 deletions AK/Utf16String.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ class [[nodiscard]] Utf16String : public Detail::Utf16StringBase {

static Utf16String from_utf16(Utf16View const& utf16_string);

// NB: These round-trip the one-word raw representation through FFI bridges (e.g. the LibWeb
// Rust style value data); the bridge releases its reference through
// Utf16FlyString::unref_raw(), which handles any Utf16StringBase-backed string.
[[nodiscard]] FlatPtr to_raw_leaked() const
{
if (has_long_storage())
data_without_union_member_assertion()->ref();
return raw();
}

[[nodiscard]] static Utf16String from_raw(FlatPtr raw)
{
Utf16String string;
auto const** data = __builtin_launder(&string.m_value.data);
*data = bit_cast<Detail::Utf16StringData const*>(raw);
if (string.has_long_storage())
string.data_without_union_member_assertion()->ref();
return string;
}

template<typename T>
requires(IsOneOf<RemoveCVReference<T>, Utf16String, Utf16FlyString>)
static Utf16String from_utf16(T&&) = delete;
Expand Down
11 changes: 11 additions & 0 deletions AK/Utf16StringBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,17 @@ class Utf16StringBase {

[[nodiscard]] constexpr FlatPtr raw(Badge<Utf16FlyString>) const { return raw(); }

// NB: Adopts a raw value previously produced by raw(), together with ownership of one
// reference to its data if it has long storage. For FFI bridges that retain the raw
// representation of a string.
[[nodiscard]] ALWAYS_INLINE static Utf16StringBase adopt_raw(Badge<Utf16FlyString>, FlatPtr raw)
{
Utf16StringBase string;
auto const** data = __builtin_launder(&string.m_value.data);
*data = bit_cast<Utf16StringData const*>(raw);
return string;
}

protected:
[[nodiscard]] constexpr FlatPtr raw() const { return bit_cast<FlatPtr>(m_value); }

Expand Down
11 changes: 11 additions & 0 deletions Libraries/LibSandbox/Seccomp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ static constexpr unsigned read_only_open_flags = O_CLOEXEC;
#define IF_DEFINED_unlinkat(if_defined, if_not_defined) if_defined
#define IF_DEFINED_umask(if_defined, if_not_defined) if_defined
#define IF_DEFINED_uname(if_defined, if_not_defined) if_defined
#define IF_DEFINED_utimensat(if_defined, if_not_defined) if_defined
#define IF_DEFINED_wait4(if_defined, if_not_defined) if_defined
#define IF_DEFINED_waitid(if_defined, if_not_defined) if_defined
#define IF_DEFINED_write(if_defined, if_not_defined) if_defined
Expand Down Expand Up @@ -472,6 +473,10 @@ static constexpr unsigned read_only_open_flags = O_CLOEXEC;
# undef IF_DEFINED_umask
# define IF_DEFINED_umask(if_defined, if_not_defined) if_not_defined
#endif
#ifndef __NR_utimensat
# undef IF_DEFINED_utimensat
# define IF_DEFINED_utimensat(if_defined, if_not_defined) if_not_defined
#endif
#ifndef __NR_wait4
# undef IF_DEFINED_wait4
# define IF_DEFINED_wait4(if_defined, if_not_defined) if_not_defined
Expand Down Expand Up @@ -685,6 +690,9 @@ static char const* syscall_name(long syscall_number)
#endif
#ifdef __NR_unlinkat
CASE_SYSCALL_NAME(unlinkat);
#endif
#ifdef __NR_utimensat
CASE_SYSCALL_NAME(utimensat);
#endif
default:
return "unknown";
Expand Down Expand Up @@ -855,6 +863,9 @@ void SeccompPolicy::allow_filesystem_writes()
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, fdatasync);
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, fallocate);
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, flock);
// NB: Mesa's shader disk cache updates entry mtimes for LRU eviction, and glibc routes the
// whole utime() family through utimensat() on modern kernels.
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, utimensat);

append(BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_fcntl, 0, 5));
append(SECCOMP_LOAD_ARGUMENT(1));
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@ endforeach()
import_rust_crate(
MANIFEST_PATH Rust/Cargo.toml
CRATE_NAME libweb_rust
FFI_HEADERS RustFFI.h SelectorRustFFI.h HTML/Parser/RustFFI.h
FFI_HEADERS RustFFI.h SelectorRustFFI.h StyleValueRustFFI.h HTML/Parser/RustFFI.h
)

set(content_blocker_rust_features "")
Expand Down
22 changes: 12 additions & 10 deletions Libraries/LibWeb/CSS/ComputedProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,10 @@ RefPtr<StyleValue const> ComputedValues::computed_style_value(PropertyID propert
auto filter_style_value = [](Filter const& filter) -> NonnullRefPtr<StyleValue const> {
if (filter.is_none())
return KeywordStyleValue::create(Keyword::None);
auto filter_values = filter.filters();
StyleValueVector filters;
MUST(filters.try_ensure_capacity(filter.filters().size()));
for (auto const& filter_value : filter.filters())
MUST(filters.try_ensure_capacity(filter_values.size()));
for (auto const& filter_value : filter_values)
filters.unchecked_append(filter_value);
return StyleValueList::create(move(filters), StyleValueList::Separator::Space, StyleValueList::Collapsible::No);
};
Expand Down Expand Up @@ -2119,11 +2120,12 @@ PreferredColorScheme ComputedProperties::color_scheme(PreferredColorScheme prefe
{
// To determine the used color scheme of an element:
auto const& scheme_value = property(PropertyID::ColorScheme).as_color_scheme();
auto schemes = scheme_value.schemes();

// 1. If the user’s preferred color scheme, as indicated by the prefers-color-scheme media feature,
// is present among the listed color schemes, and is supported by the user agent,
// that’s the element’s used color scheme.
if (preferred_scheme != PreferredColorScheme::Auto && scheme_value.schemes().contains_slow(preferred_color_scheme_to_utf16_fly_string(preferred_scheme)))
if (preferred_scheme != PreferredColorScheme::Auto && schemes.contains_slow(preferred_color_scheme_to_utf16_fly_string(preferred_scheme)))
return preferred_scheme;

// 2. Otherwise, if the user has indicated an overriding preference for their chosen color scheme,
Expand All @@ -2134,7 +2136,7 @@ PreferredColorScheme ComputedProperties::color_scheme(PreferredColorScheme prefe

// 3. Otherwise, if the user agent supports at least one of the listed color schemes,
// the used color scheme is the first supported color scheme in the list.
auto first_supported = scheme_value.schemes().first_matching([](auto scheme) { return preferred_color_scheme_from_string(scheme) != PreferredColorScheme::Auto; });
auto first_supported = schemes.first_matching([](auto scheme) { return preferred_color_scheme_from_string(scheme) != PreferredColorScheme::Auto; });
if (first_supported.has_value())
return preferred_color_scheme_from_string(first_supported.value());

Expand Down Expand Up @@ -2515,7 +2517,7 @@ Vector<BackgroundLayerData> ComputedProperties::mask_layers() const
auto property_values = [&](PropertyID property_id) {
auto const& value = property(property_id);
if (value.is_value_list())
return value.as_value_list().values();
return StyleValueVector { value.as_value_list().values() };
return StyleValueVector { value };
};

Expand Down Expand Up @@ -3226,7 +3228,7 @@ Vector<TextDecorationLine> ComputedProperties::text_decoration_line() const

if (value.is_value_list()) {
Vector<TextDecorationLine> lines;
auto& values = value.as_value_list().values();
auto values = value.as_value_list().values();
for (auto const& item : values) {
lines.append(keyword_to_text_decoration_line(item->to_keyword()).value());
}
Expand Down Expand Up @@ -3824,7 +3826,7 @@ Containment ComputedProperties::contain() const
break;
default:
if (value.is_value_list()) {
auto& values = value.as_value_list().values();
auto values = value.as_value_list().values();
for (auto const& item : values) {
switch (item->to_keyword()) {
case Keyword::Size:
Expand Down Expand Up @@ -3862,7 +3864,7 @@ Vector<Utf16FlyString> ComputedProperties::container_name() const
Vector<Utf16FlyString> names;

if (value.is_value_list()) {
auto& values = value.as_value_list().values();
auto values = value.as_value_list().values();
for (auto const& item : values)
names.append(item->as_custom_ident().custom_ident());
} else {
Expand All @@ -3882,7 +3884,7 @@ ContainerType ComputedProperties::container_type() const
return container_type;

if (value.is_value_list()) {
auto& values = value.as_value_list().values();
auto values = value.as_value_list().values();
for (auto const& item : values) {
switch (item->to_keyword()) {
case Keyword::Size:
Expand Down Expand Up @@ -4163,7 +4165,7 @@ Vector<CounterData> ComputedProperties::counter_data(PropertyID property_id) con
auto const& value = property(property_id);

if (value.is_counter_definitions()) {
auto& counter_definitions = value.as_counter_definitions().counter_definitions();
auto counter_definitions = value.as_counter_definitions().counter_definitions();
Vector<CounterData> result;
for (auto& counter : counter_definitions) {
CounterData data {
Expand Down
3 changes: 2 additions & 1 deletion Libraries/LibWeb/CSS/ComputedValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,8 @@ NonnullRefPtr<ComputedValues const> ComputedValues::create(ComputedProperties co
auto list_style_type = computed_style.list_style_type(style_scope);
auto const& list_style_type_value = computed_style.property(PropertyID::ListStyleType);
if (list_style_type_value.is_counter_style() && list_style_type_value.as_counter_style().value().has<CounterStyleStyleValue::SymbolsFunction>()) {
auto const& symbols = list_style_type_value.as_counter_style().value().get<CounterStyleStyleValue::SymbolsFunction>();
auto counter_style_value = list_style_type_value.as_counter_style().value();
auto const& symbols = counter_style_value.get<CounterStyleStyleValue::SymbolsFunction>();
auto counter_style = list_style_type.get<RefPtr<CounterStyle const>>();
VERIFY(counter_style);
list_style_type = ListStyleSymbols {
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/CSS/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Web::CSS {

StyleValueVector const& Filter::filters() const
StyleValueVector Filter::filters() const
{
VERIFY(has_filters());
return m_filter_value_list->values();
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/CSS/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Filter {
bool has_filters() const { return m_filter_value_list; }
bool is_none() const { return !has_filters(); }

StyleValueVector const& filters() const;
StyleValueVector filters() const;

private:
RefPtr<StyleValueList const> m_filter_value_list { nullptr };
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/CSS/FontFace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static FontWeightRange compute_weight_range(StyleValue const& value)
if (value.to_keyword() == Keyword::Auto || value.to_keyword() == Keyword::Normal)
return { 400, 400 };

auto& weight_values = value.as_value_list().values();
auto weight_values = value.as_value_list().values();
if (weight_values.size() == 1) {
auto one_weight = static_cast<int>(StyleComputer::compute_font_weight(weight_values[0], {})->as_number().number());
return { one_weight, one_weight };
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/GridTrackPlacement.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class GridTrackPlacement {

NonnullRefPtr<StyleValue const> line_number() const { return *m_value.get<AreaOrLine>().line_number; }
NonnullRefPtr<StyleValue const> span() const { return *m_value.get<Span>().value; }
Optional<Utf16FlyString> const& span_name() const { return m_value.get<Span>().name; }

void serialize(StringBuilder&, SerializationMode) const;
String to_string(SerializationMode mode) const;
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/CSS/GridTrackSize.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class GridTrackSizeList {
Vector<CSS::ExplicitGridTrack> track_list() const;
auto const& list() const { return m_list; }
bool is_subgrid() const { return m_is_subgrid; }
bool preserves_line_name_sets() const { return m_preserve_line_name_sets; }

void serialize(StringBuilder&, SerializationMode) const;
String to_string(SerializationMode) const;
Expand Down Expand Up @@ -170,6 +171,7 @@ class GridRepeat {
return int_from_style_value(*m_repeat_count);
}
GridTrackSizeList const& grid_track_size_list() const& { return m_grid_track_size_list; }
RefPtr<StyleValue const> repeat_count_style_value() const { return m_repeat_count; }
GridRepeatType type() const& { return m_type; }

void serialize(StringBuilder&, SerializationMode) const;
Expand Down
Loading