From e96e20c21d258d4a113a169a9073a0b1ac8b72ad Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Fri, 16 Nov 2018 16:31:22 -0800 Subject: [PATCH] Bug 1506163 - Do not span column-span:all element across all columns if it's under different block formatting context. r=bz multicol-span-all-004-ref.html is the same as multicol-span-all-004.html except for the "column-span" value in h3. Differential Revision: https://phabricator.services.mozilla.com/D12192 --- layout/base/crashtests/1506163.html | 7 ++++ layout/base/crashtests/crashtests.list | 1 + layout/base/nsCSSFrameConstructor.cpp | 35 ++++++++++------ layout/generic/nsFrameStateBits.h | 13 +++--- .../multicol-span-all-004.html.ini | 2 + .../multicol-span-all-004-ref.html | 37 +++++++++++++++++ .../css-multicol/multicol-span-all-004.html | 40 +++++++++++++++++++ 7 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 layout/base/crashtests/1506163.html create mode 100644 testing/web-platform/meta/css/css-multicol/multicol-span-all-004.html.ini create mode 100644 testing/web-platform/tests/css/css-multicol/multicol-span-all-004-ref.html create mode 100644 testing/web-platform/tests/css/css-multicol/multicol-span-all-004.html diff --git a/layout/base/crashtests/1506163.html b/layout/base/crashtests/1506163.html new file mode 100644 index 000000000000..d5fb54388f6b --- /dev/null +++ b/layout/base/crashtests/1506163.html @@ -0,0 +1,7 @@ +
  • + +
    + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 8c5b4acf4093..46181de26bc4 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -548,4 +548,5 @@ load 1490037.html load 1494332.html load 1494030.html load 1505420.html +pref(layout.css.column-span.enabled,true) load 1506163.html pref(layout.css.column-span.enabled,true) load 1506204.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index ea30cd2acb22..b8c82d4782be 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -11174,14 +11174,17 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState, } // Ensure all the children in the multi-column subtree are tagged with - // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR, except for those children in the - // column-span subtree. InitAndRestoreFrame() will add + // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR, except for those children in a new + // block formatting context. InitAndRestoreFrame() will add // mAdditionalStateBits for us. AutoRestore savedStateBits(aState.mAdditionalStateBits); if (StaticPrefs::layout_css_column_span_enabled()) { + // Multi-column container creates new block formatting context, so check + // needsColumn first to make sure we have the bit set when creating frames + // for the elements having style like "columns:3; column-span:all;". if (needsColumn) { aState.mAdditionalStateBits |= NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR; - } else if (blockFrame->IsColumnSpan()) { + } else if (blockFrame->HasAllStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS)) { aState.mAdditionalStateBits &= ~NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR; } } @@ -11392,14 +11395,22 @@ nsCSSFrameConstructor::MayNeedToCreateColumnSpanSiblings( MOZ_ASSERT(StaticPrefs::layout_css_column_span_enabled(), "Call this only when layout.css.column-span.enabled is true!"); - if (aBlockFrame->IsColumnSpan() || - !aBlockFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) { - // The children of a column-span never need to be further processed even - // if there is a nested column-span child. Because a column-span always - // creates its own block formatting context, a nested column-span child - // won't be in the same block formatting context with the nearest - // multi-column ancestor. This is the same case as if the column-span is - // outside of a multi-column hierarchy. + if (!aBlockFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) { + // The block frame isn't in a multi-column block formatting context. + return false; + } + + if (aBlockFrame->HasAllStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS) && + aBlockFrame->Style()->GetPseudo() != nsCSSAnonBoxes::columnContent()) { + // The block creates its own block formatting context, and is not the block + // representing actual column contents. + // + // For example, the children of a column-span never need to be further + // processed even if there is a nested column-span child. Because a + // column-span always creates its own block formatting context, a nested + // column-span child won't be in the same block formatting context with the + // nearest multi-column ancestor. This is the same case as if the + // column-span is outside of a multi-column hierarchy. return false; } @@ -11419,7 +11430,7 @@ nsCSSFrameConstructor::MayNeedToCreateColumnSpanSiblings( return false; } - // Need to actually look into the child items. + // Need to actually look into the child list. return true; } diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h index bfc25ebb16ac..4d871b7e46c8 100644 --- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -225,11 +225,14 @@ FRAME_STATE_BIT(Generic, 42, NS_FRAME_FONT_INFLATION_FLOW_ROOT) FRAME_STATE_BIT(Generic, 43, NS_FRAME_SVG_LAYOUT) // This bit is set if a frame has a multi-column ancestor (i.e. -// ColumnSetWrapperFrame) within the same block formatting context. A -// top-level ColumnSetWrapperFrame doesn't have this bit set, whereas a -// ColumnSetWrapperFrame nested inside a column does have this bit set. All -// the children of the column-spans do not have this bit set because they -// are in a new block formatting context created by column-spans. +// ColumnSetWrapperFrame) within the same block formatting context. A top-level +// ColumnSetWrapperFrame doesn't have this bit set, whereas a +// ColumnSetWrapperFrame nested inside a column does have this bit set. +// +// All the children of the column-spanners or any other type of frames which +// create their own block formatting context do not have this bit set because +// they are not in the same block formatting context created by a multi-column +// ancestor. FRAME_STATE_BIT(Generic, 44, NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) // Bits 45 is currently unused, but be kind and check with bug 1465474 diff --git a/testing/web-platform/meta/css/css-multicol/multicol-span-all-004.html.ini b/testing/web-platform/meta/css/css-multicol/multicol-span-all-004.html.ini new file mode 100644 index 000000000000..04bdf36d7637 --- /dev/null +++ b/testing/web-platform/meta/css/css-multicol/multicol-span-all-004.html.ini @@ -0,0 +1,2 @@ +[multicol-span-all-004.html] + prefs: [layout.css.column-span.enabled:true] diff --git a/testing/web-platform/tests/css/css-multicol/multicol-span-all-004-ref.html b/testing/web-platform/tests/css/css-multicol/multicol-span-all-004-ref.html new file mode 100644 index 000000000000..beecede21082 --- /dev/null +++ b/testing/web-platform/tests/css/css-multicol/multicol-span-all-004-ref.html @@ -0,0 +1,37 @@ + + + + CSS Multi-column Layout Test Reference: column-span:all should act like column-span:none in different block formatting context + + + + + + +
    +
    block1
    +
    +

    non-spanner

    +
    +
    +

    non-spanner

    +
    +
    + Spanner +

    non-spanner in a spanner

    +
    +
    block2
    +
    + + diff --git a/testing/web-platform/tests/css/css-multicol/multicol-span-all-004.html b/testing/web-platform/tests/css/css-multicol/multicol-span-all-004.html new file mode 100644 index 000000000000..e9165658c11f --- /dev/null +++ b/testing/web-platform/tests/css/css-multicol/multicol-span-all-004.html @@ -0,0 +1,40 @@ + + + + CSS Multi-column Layout Test: column-span:all should act like column-span:none in different block formatting context + + + + + + + + + +
    +
    block1
    +
    +

    non-spanner

    +
    +
    +

    non-spanner

    +
    +
    + Spanner +

    non-spanner in a spanner

    +
    +
    block2
    +
    + +