Skip to content

Commit 5dbcb9f

Browse files
trop[bot]zcbenzpatchup[bot]
authored
chore: cherry-pick fix for 1227933 from chromium (#30614)
* chore: cherry-pick 1227933 from chromium * chore: update patches * Update .patches * chore: update patches Co-authored-by: Cheng Zhao <[email protected]> Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
1 parent 2502e28 commit 5dbcb9f

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

patches/chromium/.patches

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,4 @@ cherry-pick-3feda0244490.patch
181181
cherry-pick-cd98d7c0dae9.patch
182182
replace_first_of_two_waitableevents_in_creditcardaccessmanager.patch
183183
cherry-pick-ac9dc1235e28.patch
184+
cherry-pick-1227933.patch
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Koji Ishii <[email protected]>
3+
Date: Mon, 26 Jul 2021 07:09:18 +0000
4+
Subject: Fix nested inline box fragmentation
5+
6+
This patch fixes when nested inline boxes are fragmented in a
7+
line due to bidi reordering.
8+
9+
Before this change, the fragmented boxes are appended to the
10+
end of |box_data_list_|. Then when |NGInlineLayoutStateStack::
11+
CreateBoxFragments| creates inline boxes in the ascending
12+
order of |box_data_list_|, it failed to add the fragmented
13+
boxes into their parent inline boxes.
14+
15+
This is critical for out-of-flow positioned objects whose
16+
containing block is an inline box, because they expect to be
17+
propagated through all ancestor inline boxes.
18+
19+
|UpdateBoxDataFragmentRange| is a little tricky by appending
20+
to a vector it is iterating. Changing it to insert to the
21+
correct position makes the function even trickier. This patch
22+
changes it to add fragmented boxes to a separate vector, and
23+
let later process |UpdateFragmentedBoxDataEdges| to merge the
24+
vector to |box_data_list_|.
25+
26+
(cherry picked from commit 9c8a39c14a9c80556468593cddf436f5047a16ce)
27+
28+
Bug: 1227933, 1229999
29+
Change-Id: I7edcd209e1fdac06bab01b16d660383e7e9c37bd
30+
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3038308
31+
Commit-Queue: Koji Ishii <[email protected]>
32+
Reviewed-by: Yoshifumi Inoue <[email protected]>
33+
Cr-Original-Commit-Position: refs/heads/master@{#903356}
34+
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3053212
35+
Commit-Queue: Rubber Stamper <[email protected]>
36+
Bot-Commit: Rubber Stamper <[email protected]>
37+
Auto-Submit: Koji Ishii <[email protected]>
38+
Cr-Commit-Position: refs/branch-heads/4577@{#145}
39+
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
40+
41+
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
42+
index c61298842eaa308b7ae863d6e1cf5457a8091dd2..f6fb0f03c3ec63c0c2de2b9501534108dea85422 100644
43+
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
44+
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
45+
@@ -4,6 +4,7 @@
46+
47+
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
48+
49+
+#include "base/containers/adapters.h"
50+
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
51+
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
52+
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
53+
@@ -389,13 +390,14 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
54+
box_data.fragment_start = box_data.fragment_end = 0;
55+
56+
// Scan children and update start/end from their box_data_index.
57+
- unsigned box_count = box_data_list_.size();
58+
+ Vector<BoxData> fragmented_boxes;
59+
for (unsigned index = 0; index < line_box->size();)
60+
- index = UpdateBoxDataFragmentRange(line_box, index);
61+
+ index = UpdateBoxDataFragmentRange(line_box, index, &fragmented_boxes);
62+
63+
- // If any inline fragmentation due to BiDi reorder, adjust box edges.
64+
- if (box_count != box_data_list_.size())
65+
- UpdateFragmentedBoxDataEdges();
66+
+ // If any inline fragmentation occurred due to BiDi reorder, append them and
67+
+ // adjust box edges.
68+
+ if (UNLIKELY(!fragmented_boxes.IsEmpty()))
69+
+ UpdateFragmentedBoxDataEdges(&fragmented_boxes);
70+
71+
#if DCHECK_IS_ON()
72+
// Check all BoxData have ranges.
73+
@@ -412,7 +414,8 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
74+
75+
unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
76+
NGLogicalLineItems* line_box,
77+
- unsigned index) {
78+
+ unsigned index,
79+
+ Vector<BoxData>* fragmented_boxes) {
80+
// Find the first line box item that should create a box fragment.
81+
for (; index < line_box->size(); index++) {
82+
NGLogicalLineItem* start = &(*line_box)[index];
83+
@@ -440,7 +443,7 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
84+
// It also changes other BoxData, but not the one we're dealing with here
85+
// because the update is limited only when its |box_data_index| is lower.
86+
while (end->box_data_index && end->box_data_index < box_data_index) {
87+
- UpdateBoxDataFragmentRange(line_box, index);
88+
+ UpdateBoxDataFragmentRange(line_box, index, fragmented_boxes);
89+
}
90+
91+
if (box_data_index != end->box_data_index)
92+
@@ -455,14 +458,9 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
93+
} else {
94+
// This box is fragmented by BiDi reordering. Add a new BoxData for the
95+
// fragmented range.
96+
- box_data_list_[box_data_index - 1].fragmented_box_data_index =
97+
- box_data_list_.size();
98+
- // Do not use `emplace_back()` here because adding to |box_data_list_| may
99+
- // reallocate the buffer, but the `BoxData` ctor must run before the
100+
- // reallocation. Create a new instance and |push_back()| instead.
101+
- BoxData fragmented_box_data(box_data_list_[box_data_index - 1],
102+
- start_index, index);
103+
- box_data_list_.push_back(fragmented_box_data);
104+
+ BoxData& fragmented_box = fragmented_boxes->emplace_back(
105+
+ box_data_list_[box_data_index - 1], start_index, index);
106+
+ fragmented_box.fragmented_box_data_index = box_data_index;
107+
}
108+
// If this box has parent boxes, we need to process it again.
109+
if (box_data_list_[box_data_index - 1].parent_box_data_index)
110+
@@ -472,7 +470,43 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
111+
return index;
112+
}
113+
114+
-void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges() {
115+
+void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges(
116+
+ Vector<BoxData>* fragmented_boxes) {
117+
+ DCHECK(!fragmented_boxes->IsEmpty());
118+
+ // Append in the descending order of |fragmented_box_data_index| because the
119+
+ // indices will change as boxes are inserted into |box_data_list_|.
120+
+ std::sort(fragmented_boxes->begin(), fragmented_boxes->end(),
121+
+ [](const BoxData& a, const BoxData& b) {
122+
+ if (a.fragmented_box_data_index != b.fragmented_box_data_index) {
123+
+ return a.fragmented_box_data_index <
124+
+ b.fragmented_box_data_index;
125+
+ }
126+
+ DCHECK_NE(a.fragment_start, b.fragment_start);
127+
+ return a.fragment_start < b.fragment_start;
128+
+ });
129+
+ for (BoxData& fragmented_box : base::Reversed(*fragmented_boxes)) {
130+
+ // Insert the fragmented box to right after the box it was fragmented from.
131+
+ // The order in the |box_data_list_| is critical when propagating child
132+
+ // fragment data such as OOF to ancestors.
133+
+ const unsigned insert_at = fragmented_box.fragmented_box_data_index;
134+
+ DCHECK_GT(insert_at, 0u);
135+
+ fragmented_box.fragmented_box_data_index = 0;
136+
+ box_data_list_.insert(insert_at, fragmented_box);
137+
+
138+
+ // Adjust box data indices by the insertion.
139+
+ for (BoxData& box_data : box_data_list_) {
140+
+ if (box_data.fragmented_box_data_index >= insert_at)
141+
+ ++box_data.fragmented_box_data_index;
142+
+ }
143+
+
144+
+ // Set the index of the last fragment to the original box. This is needed to
145+
+ // update fragment edges.
146+
+ const unsigned fragmented_from = insert_at - 1;
147+
+ if (!box_data_list_[fragmented_from].fragmented_box_data_index)
148+
+ box_data_list_[fragmented_from].fragmented_box_data_index = insert_at;
149+
+ }
150+
+
151+
+ // Move the line-right edge to the last fragment.
152+
for (BoxData& box_data : box_data_list_) {
153+
if (box_data.fragmented_box_data_index)
154+
box_data.UpdateFragmentEdges(box_data_list_);
155+
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
156+
index 36aa27914a6598671c3f9266f323ab03847db5a6..7fb13383a21116ce1dd17a327ad2cc911c3f7c01 100644
157+
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
158+
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
159+
@@ -157,17 +157,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
160+
// reordering.
161+
void UpdateAfterReorder(NGLogicalLineItems*);
162+
163+
- // Update start/end of the first BoxData found at |index|.
164+
- //
165+
- // If inline fragmentation is found, a new BoxData is added.
166+
- //
167+
- // Returns the index to process next. It should be given to the next call to
168+
- // this function.
169+
- unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, unsigned index);
170+
-
171+
- // Update edges of inline fragmented boxes.
172+
- void UpdateFragmentedBoxDataEdges();
173+
-
174+
// Compute inline positions of fragments and boxes.
175+
LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position);
176+
177+
@@ -260,6 +249,19 @@ class CORE_EXPORT NGInlineLayoutStateStack {
178+
scoped_refptr<const NGLayoutResult> CreateBoxFragment(NGLogicalLineItems*);
179+
};
180+
181+
+ // Update start/end of the first BoxData found at |index|.
182+
+ //
183+
+ // If inline fragmentation is found, a new BoxData is added.
184+
+ //
185+
+ // Returns the index to process next. It should be given to the next call to
186+
+ // this function.
187+
+ unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*,
188+
+ unsigned index,
189+
+ Vector<BoxData>* fragmented_boxes);
190+
+
191+
+ // Update edges of inline fragmented boxes.
192+
+ void UpdateFragmentedBoxDataEdges(Vector<BoxData>* fragmented_boxes);
193+
+
194+
Vector<NGInlineBoxState, 4> stack_;
195+
Vector<BoxData, 4> box_data_list_;
196+
197+
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
198+
new file mode 100644
199+
index 0000000000000000000000000000000000000000..b701d2b5688ace54aa99530c12fa8143f1e6a508
200+
--- /dev/null
201+
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
202+
@@ -0,0 +1,13 @@
203+
+<!DOCTYPE html>
204+
+<link rel="author" href="mailto:[email protected]">
205+
+<link rel="help" href="https://crbug.com/1229999">
206+
+<div style="direction:rtl; width:500px">
207+
+ <span style="border:solid">
208+
+ <span style="position:relative">
209+
+ <div style="display:inline-block; width:1000%; height:10px"></div>
210+
+ <span dir="ltr">
211+
+ <div style="position:absolute"></div>
212+
+ </span>
213+
+ </span>
214+
+ </span>
215+
+</div>

0 commit comments

Comments
 (0)