[LFC] Introduce Layout::Phase class
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2019 14:23:54 +0000 (14:23 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2019 14:23:54 +0000 (14:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200473
<rdar://problem/53996061>

Reviewed by Antti Koivisto.

It helps to check whether we could run certain actions like layout while constructing the tree.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* layout/LayoutState.h:
* layout/floats/FloatingContext.cpp:
* layout/inlineformatting/InlineLine.cpp:
* layout/layouttree/LayoutBox.cpp:
(WebCore::Layout::Box::establishesFormattingContext const):
(WebCore::Layout::Box::containingBlock const):
(WebCore::Layout::Box::formattingContextRoot const):
* layout/layouttree/LayoutTreeBuilder.cpp:
(WebCore::Layout::TreeBuilder::createLayoutTree):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248364 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/layout/LayoutPhase.cpp [new file with mode: 0644]
Source/WebCore/layout/LayoutPhase.h [new file with mode: 0644]
Source/WebCore/layout/LayoutState.cpp
Source/WebCore/layout/LayoutState.h
Source/WebCore/layout/floats/FloatingContext.cpp
Source/WebCore/layout/inlineformatting/InlineLine.cpp
Source/WebCore/layout/layouttree/LayoutBox.cpp
Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp

index 1d16e8d..e4621c3 100644 (file)
@@ -1,3 +1,25 @@
+2019-08-07  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC] Introduce Layout::Phase class
+        https://bugs.webkit.org/show_bug.cgi?id=200473
+        <rdar://problem/53996061>
+
+        Reviewed by Antti Koivisto.
+
+        It helps to check whether we could run certain actions like layout while constructing the tree.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * layout/LayoutState.h:
+        * layout/floats/FloatingContext.cpp:
+        * layout/inlineformatting/InlineLine.cpp:
+        * layout/layouttree/LayoutBox.cpp:
+        (WebCore::Layout::Box::establishesFormattingContext const):
+        (WebCore::Layout::Box::containingBlock const):
+        (WebCore::Layout::Box::formattingContextRoot const):
+        * layout/layouttree/LayoutTreeBuilder.cpp:
+        (WebCore::Layout::TreeBuilder::createLayoutTree):
+
 2019-08-07  Chris Lord  <clord@igalia.com>
 
         context-attributes-alpha-depth-stencil-antialias fails on WPE WebKit
index e54cb96..913939f 100644 (file)
@@ -1385,6 +1385,7 @@ layout/FormattingContext.cpp
 layout/FormattingContextGeometry.cpp
 layout/FormattingContextQuirks.cpp
 layout/FormattingState.cpp
+layout/LayoutPhase.cpp
 layout/LayoutState.cpp
 layout/Verification.cpp
 layout/blockformatting/BlockFormattingContext.cpp
index 372084c..b0ff4b0 100644 (file)
                6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextGeometry.cpp; sourceTree = "<group>"; };
                6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; };
                6F3E1F612136141700A65A08 /* FloatBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatBox.h; sourceTree = "<group>"; };
+               6F4A5BD522F9F16B00A80F25 /* LayoutPhase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutPhase.cpp; sourceTree = "<group>"; };
                6F73918C2106CEDD006AF262 /* LayoutUnits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutUnits.h; sourceTree = "<group>"; };
                6F7CA3C4208C2956002F29AB /* LayoutState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutState.h; sourceTree = "<group>"; };
                6F7CA3C5208C2956002F29AB /* LayoutState.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutState.cpp; sourceTree = "<group>"; };
                6FE7AA2621C37B6300296DCD /* MarginTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MarginTypes.h; sourceTree = "<group>"; };
                6FE7CFA02177EEF1005B1573 /* InlineItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineItem.h; sourceTree = "<group>"; };
                6FE9F09222211035004C5082 /* ContentChangeObserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentChangeObserver.cpp; sourceTree = "<group>"; };
+               6FEFE81D22F9D22A00114927 /* LayoutPhase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutPhase.h; sourceTree = "<group>"; };
                6FFDC43E212EFF1600A9CA91 /* FloatAvoider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatAvoider.cpp; sourceTree = "<group>"; };
                6FFDC440212EFF1600A9CA91 /* FloatAvoider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatAvoider.h; sourceTree = "<group>"; };
                709A01FD1E3D0BCC006B0D4C /* ModuleFetchFailureKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleFetchFailureKind.h; sourceTree = "<group>"; };
                                115CFA75208AFE30001E6991 /* FormattingState.cpp */,
                                115CFA74208AFE30001E6991 /* FormattingState.h */,
                                115F7805209CBCBD00739C13 /* Invalidation.h */,
+                               6F4A5BD522F9F16B00A80F25 /* LayoutPhase.cpp */,
+                               6FEFE81D22F9D22A00114927 /* LayoutPhase.h */,
                                6F7CA3C5208C2956002F29AB /* LayoutState.cpp */,
                                6F7CA3C4208C2956002F29AB /* LayoutState.h */,
                                6F73918C2106CEDD006AF262 /* LayoutUnits.h */,
diff --git a/Source/WebCore/layout/LayoutPhase.cpp b/Source/WebCore/layout/LayoutPhase.cpp
new file mode 100644 (file)
index 0000000..667b288
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LayoutPhase.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+static Phase& phase()
+{
+    static NeverDestroyed<Phase> phase;
+    return phase;
+}
+
+bool Phase::isInTreeBuilding()
+{ 
+    return *phase() && (*phase()).value() == Type::TreeBuilding;
+}
+
+bool Phase::isInLayout()
+{ 
+    return *phase() && (*phase()).value() == Type::Layout;
+}
+
+bool Phase::isInInvalidation()
+{ 
+    return *phase() && (*phase()).value() == Type::Invalidation;
+}
+
+PhaseScope::PhaseScope(Phase::Type type)
+{ 
+    // Should never nest states like calling TreeBuilding from Layout. 
+    ASSERT(!(*phase()).hasValue());
+    phase().set(type);
+}
+    
+PhaseScope::~PhaseScope()
+{
+    phase().reset();
+}
+
+}
+}
+#endif
diff --git a/Source/WebCore/layout/LayoutPhase.h b/Source/WebCore/layout/LayoutPhase.h
new file mode 100644 (file)
index 0000000..0040e0b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+class PhaseScope;
+
+class Phase {
+public:
+    enum class Type {
+        TreeBuilding,
+        Invalidation,
+        Layout
+    };
+    static bool isInTreeBuilding();
+    static bool isInLayout();
+    static bool isInInvalidation();
+
+private:
+    friend class PhaseScope;
+
+    void set(Type type) { m_type = type; }
+    void reset() { m_type = { }; }
+    Optional<Type> operator*() const { return m_type; }
+
+    Optional<Type> m_type;
+};
+
+class PhaseScope {
+public:
+    PhaseScope(Phase::Type);
+    ~PhaseScope();
+};
+
+}
+}
+#endif
index 065e3c1..bef5add 100644 (file)
@@ -38,6 +38,7 @@
 #include "Invalidation.h"
 #include "LayoutBox.h"
 #include "LayoutContainer.h"
+#include "LayoutPhase.h"
 #include "LayoutTreeBuilder.h"
 #include "RenderView.h"
 #include "TableFormattingContext.h"
@@ -71,6 +72,8 @@ LayoutState::LayoutState(const Container& initialContainingBlock)
 
 void LayoutState::updateLayout()
 {
+    PhaseScope scope(Phase::Type::Layout);
+
     ASSERT(!m_formattingContextRootListForLayout.isEmpty());
     for (auto* layoutRoot : m_formattingContextRootListForLayout)
         layoutFormattingContextSubtree(*layoutRoot);
@@ -94,6 +97,8 @@ Display::Box& LayoutState::displayBoxForLayoutBox(const Box& layoutBox) const
 
 void LayoutState::styleChanged(const Box& layoutBox, StyleDiff styleDiff)
 {
+    PhaseScope scope(Phase::Type::Invalidation);
+
     auto& formattingState = formattingStateForBox(layoutBox);
     const Container* invalidationRoot = nullptr;
     if (is<BlockFormattingState>(formattingState))
index 98dd8c5..140876d 100644 (file)
@@ -36,9 +36,7 @@
 
 namespace WebCore {
 
-#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 class RenderView;
-#endif
 
 namespace Display {
 class Box;
index 9495d33..1037501 100644 (file)
@@ -31,6 +31,7 @@
 #include "DisplayBox.h"
 #include "FloatAvoider.h"
 #include "FloatBox.h"
+#include "FormattingContext.h"
 #include "LayoutBox.h"
 #include "LayoutContainer.h"
 #include "LayoutState.h"
index 8adec1e..4f20a6f 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
+#include "InlineFormattingContext.h"
+#include "TextUtil.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
index 5cca642..edf2d4b 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "LayoutContainer.h"
+#include "LayoutPhase.h"
 #include "RenderStyle.h"
 #include <wtf/IsoMallocInlines.h>
 
@@ -65,6 +66,8 @@ Box::~Box()
 
 bool Box::establishesFormattingContext() const
 {
+    // We need the final tree structure to tell whether a box establishes a certain formatting context. 
+    ASSERT(!Phase::isInTreeBuilding());
     return establishesBlockFormattingContext() || establishesInlineFormattingContext() || establishesTableFormattingContext();
 }
 
@@ -177,6 +180,8 @@ bool Box::isFloatAvoider() const
 
 const Container* Box::containingBlock() const
 {
+    // Finding the containing block by traversing the tree during tree construction could provide incorrect result.
+    ASSERT(!Phase::isInTreeBuilding());
     // The containing block in which the root element lives is a rectangle called the initial containing block.
     // For other elements, if the element's position is 'relative' or 'static', the containing block is formed by the
     // content edge of the nearest block container ancestor box.
@@ -210,6 +215,8 @@ const Container* Box::containingBlock() const
 
 const Container& Box::formattingContextRoot() const
 {
+    // Finding the context root by traversing the tree during tree construction could provide incorrect result.
+    ASSERT(!Phase::isInTreeBuilding());
     // We should never need to ask this question on the ICB.
     ASSERT(!isInitialContainingBlock());
     // A box lives in the same formatting context as its containing block unless the containing block establishes a formatting context.
index ca310a9..5feecee 100644 (file)
@@ -35,6 +35,7 @@
 #include "LayoutChildIterator.h"
 #include "LayoutContainer.h"
 #include "LayoutDescendantIterator.h"
+#include "LayoutPhase.h"
 #include "LayoutState.h"
 #include "RenderBlock.h"
 #include "RenderChildIterator.h"
@@ -69,6 +70,8 @@ static void appendChild(Container& parent, Box& newChild)
 
 std::unique_ptr<Container> TreeBuilder::createLayoutTree(const RenderView& renderView)
 {
+    PhaseScope scope(Phase::Type::TreeBuilding);
+
     auto style = RenderStyle::clone(renderView.style());
     style.setLogicalWidth(Length(renderView.width(), Fixed));
     style.setLogicalHeight(Length(renderView.height(), Fixed));