From 5dbcb9fe102e5687049fd2457111efbafd9a9e5c Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 08:21:59 +0900 Subject: [PATCH] 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 Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com> --- patches/chromium/.patches | 1 + patches/chromium/cherry-pick-1227933.patch | 215 +++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 patches/chromium/cherry-pick-1227933.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 3964c31b51fb1..53a2e796021a4 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -181,3 +181,4 @@ cherry-pick-3feda0244490.patch cherry-pick-cd98d7c0dae9.patch replace_first_of_two_waitableevents_in_creditcardaccessmanager.patch cherry-pick-ac9dc1235e28.patch +cherry-pick-1227933.patch diff --git a/patches/chromium/cherry-pick-1227933.patch b/patches/chromium/cherry-pick-1227933.patch new file mode 100644 index 0000000000000..abbdf26d4e598 --- /dev/null +++ b/patches/chromium/cherry-pick-1227933.patch @@ -0,0 +1,215 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Koji Ishii +Date: Mon, 26 Jul 2021 07:09:18 +0000 +Subject: Fix nested inline box fragmentation + +This patch fixes when nested inline boxes are fragmented in a +line due to bidi reordering. + +Before this change, the fragmented boxes are appended to the +end of |box_data_list_|. Then when |NGInlineLayoutStateStack:: +CreateBoxFragments| creates inline boxes in the ascending +order of |box_data_list_|, it failed to add the fragmented +boxes into their parent inline boxes. + +This is critical for out-of-flow positioned objects whose +containing block is an inline box, because they expect to be +propagated through all ancestor inline boxes. + +|UpdateBoxDataFragmentRange| is a little tricky by appending +to a vector it is iterating. Changing it to insert to the +correct position makes the function even trickier. This patch +changes it to add fragmented boxes to a separate vector, and +let later process |UpdateFragmentedBoxDataEdges| to merge the +vector to |box_data_list_|. + +(cherry picked from commit 9c8a39c14a9c80556468593cddf436f5047a16ce) + +Bug: 1227933, 1229999 +Change-Id: I7edcd209e1fdac06bab01b16d660383e7e9c37bd +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3038308 +Commit-Queue: Koji Ishii +Reviewed-by: Yoshifumi Inoue +Cr-Original-Commit-Position: refs/heads/master@{#903356} +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3053212 +Commit-Queue: Rubber Stamper +Bot-Commit: Rubber Stamper +Auto-Submit: Koji Ishii +Cr-Commit-Position: refs/branch-heads/4577@{#145} +Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210} + +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 +index c61298842eaa308b7ae863d6e1cf5457a8091dd2..f6fb0f03c3ec63c0c2de2b9501534108dea85422 100644 +--- 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 +@@ -4,6 +4,7 @@ + + #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h" + ++#include "base/containers/adapters.h" + #include "third_party/blink/renderer/core/layout/geometry/logical_offset.h" + #include "third_party/blink/renderer/core/layout/geometry/logical_size.h" + #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h" +@@ -389,13 +390,14 @@ void NGInlineLayoutStateStack::UpdateAfterReorder( + box_data.fragment_start = box_data.fragment_end = 0; + + // Scan children and update start/end from their box_data_index. +- unsigned box_count = box_data_list_.size(); ++ Vector fragmented_boxes; + for (unsigned index = 0; index < line_box->size();) +- index = UpdateBoxDataFragmentRange(line_box, index); ++ index = UpdateBoxDataFragmentRange(line_box, index, &fragmented_boxes); + +- // If any inline fragmentation due to BiDi reorder, adjust box edges. +- if (box_count != box_data_list_.size()) +- UpdateFragmentedBoxDataEdges(); ++ // If any inline fragmentation occurred due to BiDi reorder, append them and ++ // adjust box edges. ++ if (UNLIKELY(!fragmented_boxes.IsEmpty())) ++ UpdateFragmentedBoxDataEdges(&fragmented_boxes); + + #if DCHECK_IS_ON() + // Check all BoxData have ranges. +@@ -412,7 +414,8 @@ void NGInlineLayoutStateStack::UpdateAfterReorder( + + unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange( + NGLogicalLineItems* line_box, +- unsigned index) { ++ unsigned index, ++ Vector* fragmented_boxes) { + // Find the first line box item that should create a box fragment. + for (; index < line_box->size(); index++) { + NGLogicalLineItem* start = &(*line_box)[index]; +@@ -440,7 +443,7 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange( + // It also changes other BoxData, but not the one we're dealing with here + // because the update is limited only when its |box_data_index| is lower. + while (end->box_data_index && end->box_data_index < box_data_index) { +- UpdateBoxDataFragmentRange(line_box, index); ++ UpdateBoxDataFragmentRange(line_box, index, fragmented_boxes); + } + + if (box_data_index != end->box_data_index) +@@ -455,14 +458,9 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange( + } else { + // This box is fragmented by BiDi reordering. Add a new BoxData for the + // fragmented range. +- box_data_list_[box_data_index - 1].fragmented_box_data_index = +- box_data_list_.size(); +- // Do not use `emplace_back()` here because adding to |box_data_list_| may +- // reallocate the buffer, but the `BoxData` ctor must run before the +- // reallocation. Create a new instance and |push_back()| instead. +- BoxData fragmented_box_data(box_data_list_[box_data_index - 1], +- start_index, index); +- box_data_list_.push_back(fragmented_box_data); ++ BoxData& fragmented_box = fragmented_boxes->emplace_back( ++ box_data_list_[box_data_index - 1], start_index, index); ++ fragmented_box.fragmented_box_data_index = box_data_index; + } + // If this box has parent boxes, we need to process it again. + if (box_data_list_[box_data_index - 1].parent_box_data_index) +@@ -472,7 +470,43 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange( + return index; + } + +-void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges() { ++void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges( ++ Vector* fragmented_boxes) { ++ DCHECK(!fragmented_boxes->IsEmpty()); ++ // Append in the descending order of |fragmented_box_data_index| because the ++ // indices will change as boxes are inserted into |box_data_list_|. ++ std::sort(fragmented_boxes->begin(), fragmented_boxes->end(), ++ [](const BoxData& a, const BoxData& b) { ++ if (a.fragmented_box_data_index != b.fragmented_box_data_index) { ++ return a.fragmented_box_data_index < ++ b.fragmented_box_data_index; ++ } ++ DCHECK_NE(a.fragment_start, b.fragment_start); ++ return a.fragment_start < b.fragment_start; ++ }); ++ for (BoxData& fragmented_box : base::Reversed(*fragmented_boxes)) { ++ // Insert the fragmented box to right after the box it was fragmented from. ++ // The order in the |box_data_list_| is critical when propagating child ++ // fragment data such as OOF to ancestors. ++ const unsigned insert_at = fragmented_box.fragmented_box_data_index; ++ DCHECK_GT(insert_at, 0u); ++ fragmented_box.fragmented_box_data_index = 0; ++ box_data_list_.insert(insert_at, fragmented_box); ++ ++ // Adjust box data indices by the insertion. ++ for (BoxData& box_data : box_data_list_) { ++ if (box_data.fragmented_box_data_index >= insert_at) ++ ++box_data.fragmented_box_data_index; ++ } ++ ++ // Set the index of the last fragment to the original box. This is needed to ++ // update fragment edges. ++ const unsigned fragmented_from = insert_at - 1; ++ if (!box_data_list_[fragmented_from].fragmented_box_data_index) ++ box_data_list_[fragmented_from].fragmented_box_data_index = insert_at; ++ } ++ ++ // Move the line-right edge to the last fragment. + for (BoxData& box_data : box_data_list_) { + if (box_data.fragmented_box_data_index) + box_data.UpdateFragmentEdges(box_data_list_); +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 +index 36aa27914a6598671c3f9266f323ab03847db5a6..7fb13383a21116ce1dd17a327ad2cc911c3f7c01 100644 +--- 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 +@@ -157,17 +157,6 @@ class CORE_EXPORT NGInlineLayoutStateStack { + // reordering. + void UpdateAfterReorder(NGLogicalLineItems*); + +- // Update start/end of the first BoxData found at |index|. +- // +- // If inline fragmentation is found, a new BoxData is added. +- // +- // Returns the index to process next. It should be given to the next call to +- // this function. +- unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, unsigned index); +- +- // Update edges of inline fragmented boxes. +- void UpdateFragmentedBoxDataEdges(); +- + // Compute inline positions of fragments and boxes. + LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position); + +@@ -260,6 +249,19 @@ class CORE_EXPORT NGInlineLayoutStateStack { + scoped_refptr CreateBoxFragment(NGLogicalLineItems*); + }; + ++ // Update start/end of the first BoxData found at |index|. ++ // ++ // If inline fragmentation is found, a new BoxData is added. ++ // ++ // Returns the index to process next. It should be given to the next call to ++ // this function. ++ unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, ++ unsigned index, ++ Vector* fragmented_boxes); ++ ++ // Update edges of inline fragmented boxes. ++ void UpdateFragmentedBoxDataEdges(Vector* fragmented_boxes); ++ + Vector stack_; + Vector box_data_list_; + +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 +new file mode 100644 +index 0000000000000000000000000000000000000000..b701d2b5688ace54aa99530c12fa8143f1e6a508 +--- /dev/null ++++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html +@@ -0,0 +1,13 @@ ++ ++ ++ ++
++ ++ ++
++ ++
++
++
++
++