mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-13 03:29:49 +00:00
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);
```
This commit is contained in:
parent
73a4b176cf
commit
a4463c45b9
Notes:
github-actions[bot]
2025-03-08 13:53:25 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: a4463c45b9
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3857
13 changed files with 108 additions and 102 deletions
|
@ -147,7 +147,7 @@ WebIDL::ExceptionOr<void> CharacterData::replace_data(size_t offset, size_t coun
|
|||
static_cast<Layout::TextNode&>(*layout_node).invalidate_text_for_rendering();
|
||||
|
||||
// We also need to relayout.
|
||||
document().set_needs_layout(SetNeedsLayoutReason::CharacterDataReplaceData);
|
||||
set_needs_layout_update(SetNeedsLayoutReason::CharacterDataReplaceData);
|
||||
}
|
||||
|
||||
document().bump_character_data_version();
|
||||
|
|
|
@ -1211,20 +1211,6 @@ Optional<String> Document::encoding_parse_and_serialize_url(StringView url) cons
|
|||
return parsed_url->serialize();
|
||||
}
|
||||
|
||||
void Document::set_needs_layout(SetNeedsLayoutReason reason)
|
||||
{
|
||||
if (m_needs_layout)
|
||||
return;
|
||||
if constexpr (UPDATE_LAYOUT_DEBUG) {
|
||||
// NOTE: We check some conditions here to avoid debug spam in documents that don't do layout.
|
||||
auto navigable = this->navigable();
|
||||
if (m_layout_root && navigable && navigable->active_document() == this)
|
||||
dbgln_if(UPDATE_LAYOUT_DEBUG, "NEED LAYOUT {}", to_string(reason));
|
||||
}
|
||||
m_needs_layout = true;
|
||||
schedule_layout_update();
|
||||
}
|
||||
|
||||
void Document::invalidate_layout_tree(InvalidateLayoutTreeReason reason)
|
||||
{
|
||||
if (m_layout_root)
|
||||
|
@ -1299,7 +1285,7 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
|
||||
update_style();
|
||||
|
||||
if (!m_needs_layout && m_layout_root)
|
||||
if (!m_needs_layout_update && m_layout_root)
|
||||
return;
|
||||
|
||||
// NOTE: If this is a document hosting <template> contents, layout is unnecessary.
|
||||
|
@ -1329,11 +1315,16 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
}
|
||||
}
|
||||
|
||||
// Assign each box that establishes a formatting context a list of absolutely positioned children it should take care of during layout
|
||||
m_layout_root->for_each_in_inclusive_subtree_of_type<Layout::Box>([&](auto& child) {
|
||||
bool needs_layout_update = child.dom_node() && child.dom_node()->needs_layout_update();
|
||||
if (needs_layout_update || child.is_anonymous()) {
|
||||
child.reset_cached_intrinsic_sizes();
|
||||
}
|
||||
child.clear_contained_abspos_children();
|
||||
return TraversalDecision::Continue;
|
||||
});
|
||||
|
||||
// Assign each box that establishes a formatting context a list of absolutely positioned children it should take care of during layout
|
||||
m_layout_root->for_each_in_inclusive_subtree([&](auto& child) {
|
||||
if (!child.is_absolutely_positioned())
|
||||
return TraversalDecision::Continue;
|
||||
|
@ -1396,7 +1387,10 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
paintable()->recompute_selection_states(*range);
|
||||
}
|
||||
|
||||
m_needs_layout = false;
|
||||
for_each_shadow_including_inclusive_descendant([](auto& node) {
|
||||
node.reset_needs_layout_update();
|
||||
return TraversalDecision::Continue;
|
||||
});
|
||||
|
||||
// Scrolling by zero offset will clamp scroll offset back to valid range if it was out of bounds
|
||||
// after the viewport size change.
|
||||
|
@ -1430,6 +1424,9 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
}
|
||||
is_display_none = static_cast<Element&>(node).computed_properties()->display().is_none();
|
||||
}
|
||||
if (node_invalidation.relayout) {
|
||||
node.set_needs_layout_update(SetNeedsLayoutReason::StyleChange);
|
||||
}
|
||||
if (node_invalidation.rebuild_layout_tree) {
|
||||
// We mark layout tree for rebuild starting from parent element to correctly invalidate
|
||||
// "display" property change to/from "contents" value.
|
||||
|
@ -1441,6 +1438,7 @@ void Document::update_layout(UpdateLayoutReason reason)
|
|||
}
|
||||
invalidation |= node_invalidation;
|
||||
node.set_needs_style_update(false);
|
||||
invalidation |= node_invalidation;
|
||||
|
||||
bool children_need_inherited_style_update = !invalidation.is_none();
|
||||
if (needs_full_style_update || node.child_needs_style_update() || children_need_inherited_style_update) {
|
||||
|
@ -1532,8 +1530,6 @@ void Document::update_style()
|
|||
auto invalidation = update_style_recursively(*this, style_computer(), false);
|
||||
if (!invalidation.is_none())
|
||||
invalidate_display_list();
|
||||
if (invalidation.relayout)
|
||||
set_needs_layout(SetNeedsLayoutReason::StyleChange);
|
||||
if (invalidation.rebuild_stacking_context_tree)
|
||||
invalidate_stacking_context_tree();
|
||||
m_needs_full_style_update = false;
|
||||
|
|
|
@ -50,26 +50,6 @@ enum class QuirksMode {
|
|||
Yes
|
||||
};
|
||||
|
||||
#define ENUMERATE_SET_NEEDS_LAYOUT_REASONS(X) \
|
||||
X(CharacterDataReplaceData) \
|
||||
X(FinalizeACrossDocumentNavigation) \
|
||||
X(HTMLImageElementReactToChangesInTheEnvironment) \
|
||||
X(HTMLImageElementUpdateTheImageData) \
|
||||
X(HTMLVideoElementSetVideoTrack) \
|
||||
X(KeyframeEffect) \
|
||||
X(LayoutTreeUpdate) \
|
||||
X(NavigableSetViewportSize) \
|
||||
X(SVGImageElementFetchTheDocument) \
|
||||
X(StyleChange)
|
||||
|
||||
enum class SetNeedsLayoutReason {
|
||||
#define ENUMERATE_SET_NEEDS_LAYOUT_REASON(e) e,
|
||||
ENUMERATE_SET_NEEDS_LAYOUT_REASONS(ENUMERATE_SET_NEEDS_LAYOUT_REASON)
|
||||
#undef ENUMERATE_SET_NEEDS_LAYOUT_REASON
|
||||
};
|
||||
|
||||
[[nodiscard]] StringView to_string(SetNeedsLayoutReason);
|
||||
|
||||
#define ENUMERATE_INVALIDATE_LAYOUT_TREE_REASONS(X) \
|
||||
X(DocumentAddAnElementToTheTopLayer) \
|
||||
X(DocumentRequestAnElementToBeRemovedFromTheTopLayer) \
|
||||
|
@ -358,8 +338,6 @@ public:
|
|||
void update_paint_and_hit_testing_properties_if_needed();
|
||||
void update_animated_style_if_needed();
|
||||
|
||||
void set_needs_layout(SetNeedsLayoutReason);
|
||||
|
||||
void invalidate_layout_tree(InvalidateLayoutTreeReason);
|
||||
void invalidate_stacking_context_tree();
|
||||
|
||||
|
@ -1076,8 +1054,6 @@ private:
|
|||
// Used by evaluate_media_queries_and_report_changes().
|
||||
Vector<WeakPtr<CSS::MediaQueryList>> m_media_query_lists;
|
||||
|
||||
bool m_needs_layout { false };
|
||||
|
||||
bool m_needs_full_style_update { false };
|
||||
bool m_needs_full_layout_tree_update { false };
|
||||
|
||||
|
|
|
@ -1405,7 +1405,7 @@ void Node::set_needs_layout_tree_update(bool value)
|
|||
break;
|
||||
ancestor->m_child_needs_layout_tree_update = true;
|
||||
}
|
||||
document().set_needs_layout(SetNeedsLayoutReason::LayoutTreeUpdate);
|
||||
set_needs_layout_update(SetNeedsLayoutReason::LayoutTreeUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,6 +1425,27 @@ void Node::set_needs_style_update(bool value)
|
|||
}
|
||||
}
|
||||
|
||||
void Node::set_needs_layout_update(SetNeedsLayoutReason reason)
|
||||
{
|
||||
if (m_needs_layout_update)
|
||||
return;
|
||||
|
||||
if constexpr (UPDATE_LAYOUT_DEBUG) {
|
||||
// NOTE: We check some conditions here to avoid debug spam in documents that don't do layout.
|
||||
auto navigable = this->navigable();
|
||||
if (navigable && navigable->active_document() == this)
|
||||
dbgln_if(UPDATE_LAYOUT_DEBUG, "NEED LAYOUT {}", to_string(reason));
|
||||
}
|
||||
|
||||
m_needs_layout_update = true;
|
||||
|
||||
for (auto* ancestor = parent_or_shadow_host(); ancestor; ancestor = ancestor->parent_or_shadow_host()) {
|
||||
if (ancestor->m_needs_layout_update)
|
||||
break;
|
||||
ancestor->m_needs_layout_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Node::post_connection()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -91,6 +91,26 @@ enum class StyleInvalidationReason {
|
|||
#undef __ENUMERATE_STYLE_INVALIDATION_REASON
|
||||
};
|
||||
|
||||
#define ENUMERATE_SET_NEEDS_LAYOUT_REASONS(X) \
|
||||
X(CharacterDataReplaceData) \
|
||||
X(FinalizeACrossDocumentNavigation) \
|
||||
X(HTMLImageElementReactToChangesInTheEnvironment) \
|
||||
X(HTMLImageElementUpdateTheImageData) \
|
||||
X(HTMLVideoElementSetVideoTrack) \
|
||||
X(KeyframeEffect) \
|
||||
X(LayoutTreeUpdate) \
|
||||
X(NavigableSetViewportSize) \
|
||||
X(SVGImageElementFetchTheDocument) \
|
||||
X(StyleChange)
|
||||
|
||||
enum class SetNeedsLayoutReason {
|
||||
#define ENUMERATE_SET_NEEDS_LAYOUT_REASON(e) e,
|
||||
ENUMERATE_SET_NEEDS_LAYOUT_REASONS(ENUMERATE_SET_NEEDS_LAYOUT_REASON)
|
||||
#undef ENUMERATE_SET_NEEDS_LAYOUT_REASON
|
||||
};
|
||||
|
||||
[[nodiscard]] StringView to_string(SetNeedsLayoutReason);
|
||||
|
||||
class Node : public EventTarget
|
||||
, public TreeNode<Node> {
|
||||
WEB_PLATFORM_OBJECT(Node, EventTarget);
|
||||
|
@ -291,6 +311,10 @@ public:
|
|||
void set_needs_style_update(bool);
|
||||
void set_needs_style_update_internal(bool) { m_needs_style_update = true; }
|
||||
|
||||
bool needs_layout_update() const { return m_needs_layout_update; }
|
||||
void set_needs_layout_update(SetNeedsLayoutReason);
|
||||
void reset_needs_layout_update() { m_needs_layout_update = false; }
|
||||
|
||||
bool child_needs_style_update() const { return m_child_needs_style_update; }
|
||||
void set_child_needs_style_update(bool b) { m_child_needs_style_update = b; }
|
||||
|
||||
|
@ -528,6 +552,8 @@ protected:
|
|||
bool m_child_needs_style_update { false };
|
||||
bool m_entire_subtree_needs_style_update { false };
|
||||
|
||||
bool m_needs_layout_update { false };
|
||||
|
||||
UniqueNodeID m_unique_id;
|
||||
|
||||
// https://dom.spec.whatwg.org/#registered-observer-list
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue