LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
2026-06-06 09:03:41 -03:00
|
|
|
#include <LibGC/WeakInlines.h>
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
#include <LibWeb/CSS/CSSStyleDeclaration.h>
|
|
|
|
|
#include <LibWeb/CSS/CascadedProperties.h>
|
2025-10-24 10:11:58 -03:00
|
|
|
#include <LibWeb/CSS/PropertyID.h>
|
2025-02-05 08:54:17 -03:00
|
|
|
#include <LibWeb/DOM/Element.h>
|
2026-04-22 03:52:18 -03:00
|
|
|
#include <LibWeb/DOM/ShadowRoot.h>
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
|
|
|
|
|
namespace Web::CSS {
|
2025-05-13 08:06:33 -03:00
|
|
|
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
CascadedProperties::CascadedProperties() = default;
|
|
|
|
|
|
|
|
|
|
CascadedProperties::~CascadedProperties() = default;
|
|
|
|
|
|
2026-06-06 09:03:41 -03:00
|
|
|
NonnullRefPtr<CascadedProperties> CascadedProperties::create()
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
{
|
2026-06-06 09:03:41 -03:00
|
|
|
return adopt_ref(*new CascadedProperties);
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CascadedProperties::revert_property(PropertyID property_id, Important important, CascadeOrigin cascade_origin)
|
|
|
|
|
{
|
|
|
|
|
auto it = m_properties.find(property_id);
|
|
|
|
|
if (it == m_properties.end())
|
|
|
|
|
return;
|
|
|
|
|
auto& entries = it->value;
|
|
|
|
|
entries.remove_all_matching([&](auto& entry) {
|
2026-04-30 06:44:26 -03:00
|
|
|
// https://drafts.csswg.org/css-cascade-5/#author-presentational-hint-origin
|
|
|
|
|
// For the purpose of cascading this author presentational hint origin is treated as an independent origin, but
|
|
|
|
|
// for the purpose of the revert keyword it is considered part of the author origin.
|
|
|
|
|
auto origin_matches = entry.origin == cascade_origin
|
|
|
|
|
|| (cascade_origin == CascadeOrigin::Author && entry.origin == CascadeOrigin::AuthorPresentationalHint);
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
return entry.property.property_id == property_id
|
|
|
|
|
&& entry.property.important == important
|
2026-04-30 06:44:26 -03:00
|
|
|
&& origin_matches;
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
});
|
2026-01-26 23:25:59 -03:00
|
|
|
if (entries.is_empty()) {
|
|
|
|
|
m_contained_properties_cache.set(to_underlying(property_id), false);
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
m_properties.remove(it);
|
2026-01-26 23:25:59 -03:00
|
|
|
}
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
LibWeb: Account for shadow contexts in the cascade
Apply author declarations in encapsulation-context order before layer,
specificity, scope proximity, and source-order tie breaking. Normal
author rules now cascade from inner shadow contexts outward. This lets
outer contexts override component defaults. Important author rules
cascade the other way so inner contexts can enforce requirements.
Keep the ordering context-bucketed. The common document-only path still
collects and sorts one author context. Custom properties follow the same
context order. var() substitution now observes the same winners as
longhand properties.
Make revert-layer remove declarations only from the matching cascade
origin, context, and layer. This keeps presentational hints and values
from other shadow contexts available when one context rolls back its own
layer.
Add coverage for document and shadow-host competition, slotted rules,
nested slot contexts, inline styles, important declarations, custom
properties, and revert-layer across shadow contexts.
2026-05-31 06:18:12 -03:00
|
|
|
void CascadedProperties::revert_layer_property(PropertyID property_id, Important important, CascadeOrigin cascade_origin, Optional<FlyString> layer_name, GC::Ptr<DOM::ShadowRoot const> source_shadow_root)
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
{
|
|
|
|
|
auto it = m_properties.find(property_id);
|
|
|
|
|
if (it == m_properties.end())
|
|
|
|
|
return;
|
|
|
|
|
auto& entries = it->value;
|
|
|
|
|
entries.remove_all_matching([&](auto& entry) {
|
|
|
|
|
return entry.property.property_id == property_id
|
|
|
|
|
&& entry.property.important == important
|
LibWeb: Account for shadow contexts in the cascade
Apply author declarations in encapsulation-context order before layer,
specificity, scope proximity, and source-order tie breaking. Normal
author rules now cascade from inner shadow contexts outward. This lets
outer contexts override component defaults. Important author rules
cascade the other way so inner contexts can enforce requirements.
Keep the ordering context-bucketed. The common document-only path still
collects and sorts one author context. Custom properties follow the same
context order. var() substitution now observes the same winners as
longhand properties.
Make revert-layer remove declarations only from the matching cascade
origin, context, and layer. This keeps presentational hints and values
from other shadow contexts available when one context rolls back its own
layer.
Add coverage for document and shadow-host competition, slotted rules,
nested slot contexts, inline styles, important declarations, custom
properties, and revert-layer across shadow contexts.
2026-05-31 06:18:12 -03:00
|
|
|
&& entry.origin == cascade_origin
|
2026-06-06 09:03:41 -03:00
|
|
|
&& entry.source_shadow_root.ptr() == source_shadow_root
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
&& layer_name == entry.layer_name;
|
|
|
|
|
});
|
2026-01-26 23:25:59 -03:00
|
|
|
if (entries.is_empty()) {
|
|
|
|
|
m_contained_properties_cache.set(to_underlying(property_id), false);
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
m_properties.remove(it);
|
2026-01-26 23:25:59 -03:00
|
|
|
}
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
2026-04-22 03:52:18 -03:00
|
|
|
void CascadedProperties::set_property(PropertyID property_id, NonnullRefPtr<StyleValue const> value, Important important, CascadeOrigin origin, Optional<FlyString> layer_name, GC::Ptr<CSS::CSSStyleDeclaration const> source, GC::Ptr<DOM::ShadowRoot const> source_shadow_root)
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
{
|
2026-01-26 23:25:59 -03:00
|
|
|
m_contained_properties_cache.set(to_underlying(property_id), true);
|
|
|
|
|
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
auto& entries = m_properties.ensure(property_id);
|
|
|
|
|
|
|
|
|
|
for (auto& entry : entries.in_reverse()) {
|
2026-06-06 09:03:41 -03:00
|
|
|
if (entry.origin == origin && entry.layer_name == layer_name && entry.source_shadow_root.ptr() == source_shadow_root) {
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
if (entry.property.important == Important::Yes && important == Important::No)
|
|
|
|
|
return;
|
|
|
|
|
entry.property = StyleProperty {
|
|
|
|
|
.important = important,
|
|
|
|
|
.property_id = property_id,
|
|
|
|
|
.value = value,
|
|
|
|
|
};
|
2026-03-15 08:12:25 -03:00
|
|
|
entry.cascade_index = m_next_cascade_index++;
|
2026-06-06 09:03:41 -03:00
|
|
|
entry.source = source.ptr();
|
|
|
|
|
entry.source_shadow_root = source_shadow_root.ptr();
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entries.append(Entry {
|
|
|
|
|
.property = StyleProperty {
|
|
|
|
|
.important = important,
|
|
|
|
|
.property_id = property_id,
|
|
|
|
|
.value = value,
|
|
|
|
|
},
|
2026-03-15 08:12:25 -03:00
|
|
|
.cascade_index = m_next_cascade_index++,
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
.origin = origin,
|
|
|
|
|
.layer_name = move(layer_name),
|
2026-06-06 09:03:41 -03:00
|
|
|
.source = source.ptr(),
|
|
|
|
|
.source_shadow_root = source_shadow_root.ptr(),
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-08 06:11:51 -03:00
|
|
|
RefPtr<StyleValue const> CascadedProperties::property(PropertyID property_id) const
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
{
|
2026-01-26 23:25:59 -03:00
|
|
|
if (!m_contained_properties_cache.get(to_underlying(property_id)))
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
return nullptr;
|
|
|
|
|
|
2026-01-26 23:25:59 -03:00
|
|
|
return m_properties.get(property_id)->last().property.value;
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 01:51:24 -03:00
|
|
|
PropertyID CascadedProperties::property_with_higher_priority(PropertyID first_property_id, PropertyID second_property_id) const
|
|
|
|
|
{
|
|
|
|
|
if (!m_contained_properties_cache.get(to_underlying(first_property_id)))
|
|
|
|
|
return second_property_id;
|
|
|
|
|
|
|
|
|
|
if (!m_contained_properties_cache.get(to_underlying(second_property_id)))
|
|
|
|
|
return first_property_id;
|
|
|
|
|
|
|
|
|
|
if (m_properties.get(first_property_id)->last().cascade_index >= m_properties.get(second_property_id)->last().cascade_index)
|
|
|
|
|
return first_property_id;
|
|
|
|
|
|
|
|
|
|
return second_property_id;
|
|
|
|
|
}
|
|
|
|
|
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
GC::Ptr<CSSStyleDeclaration const> CascadedProperties::property_source(PropertyID property_id) const
|
|
|
|
|
{
|
2026-01-26 23:25:59 -03:00
|
|
|
if (!m_contained_properties_cache.get(to_underlying(property_id)))
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
return nullptr;
|
|
|
|
|
|
2026-06-06 09:03:41 -03:00
|
|
|
return m_properties.get(property_id)->last().source.ptr();
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
2026-04-22 03:52:18 -03:00
|
|
|
GC::Ptr<DOM::ShadowRoot const> CascadedProperties::property_source_shadow_root(PropertyID property_id) const
|
|
|
|
|
{
|
|
|
|
|
if (!m_contained_properties_cache.get(to_underlying(property_id)))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
2026-06-06 09:03:41 -03:00
|
|
|
return m_properties.get(property_id)->last().source_shadow_root.ptr();
|
2026-04-22 03:52:18 -03:00
|
|
|
}
|
|
|
|
|
|
2026-01-10 23:55:53 -03:00
|
|
|
Optional<StyleProperty> CascadedProperties::style_property(PropertyID property_id) const
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
{
|
2026-01-26 23:25:59 -03:00
|
|
|
if (!m_contained_properties_cache.get(to_underlying(property_id)))
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
return m_properties.get(property_id)->last().property;
|
LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.
This worked great, but it meant we had to do all the work of selector
matching and cascading every time.
To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.
The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.
Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-12 06:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|