layout: Add incremental box tree construction for inline boxes (#38084)

This changes extend the incremental box tree construction for inline
boxes. Since an `InlineItem` can be split into multiple `InlineItem`s by
a block element, the reason such an inline item is marked as damaged may
simply be the removal of the block element or the need to reconstruct
its box tree. Therefore, under the current LayoutDamage design,
theoretically, even damaged inline items might still have some of their
splits reusable. However, based on the principle of simplicity and
effectiveness, this PR only considers reusing undamaged inline boxes.

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
This commit is contained in:
JoeDow 2025-07-25 19:49:46 +08:00 committed by GitHub
parent 3f1e170410
commit 5cd57f9dba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 23 deletions

View file

@ -466,6 +466,7 @@ impl<'dom> BlockContainerBuilder<'dom, '_> {
contents: Contents,
box_slot: BoxSlot<'dom>,
) {
let old_layout_box = box_slot.take_layout_box_if_undamaged(info.damage);
let (is_list_item, non_replaced_contents) = match (display_inside, contents) {
(
DisplayInside::Flow { is_list_item },
@ -485,7 +486,7 @@ impl<'dom> BlockContainerBuilder<'dom, '_> {
propagated_data,
))
};
let old_layout_box = box_slot.take_layout_box_if_undamaged(info.damage);
let atomic = self
.ensure_inline_formatting_context_builder()
.push_atomic(construction_callback, old_layout_box);
@ -497,7 +498,11 @@ impl<'dom> BlockContainerBuilder<'dom, '_> {
// Otherwise, this is just a normal inline box. Whatever happened before, all we need to do
// before recurring is to remember this ongoing inline level box.
self.ensure_inline_formatting_context_builder()
.start_inline_box(InlineBox::new(info), None);
.start_inline_box(
|| ArcRefCell::new(InlineBox::new(info)),
None,
old_layout_box,
);
if is_list_item {
if let Some((marker_info, marker_contents)) =