WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-238589-20220420132218.patch (text/plain), 22.45 KB, created by
Simon Fraser (smfr)
on 2022-04-20 13:22:19 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Simon Fraser (smfr)
Created:
2022-04-20 13:22:19 PDT
Size:
22.45 KB
patch
obsolete
>Subversion Revision: 292975 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index db7e6cbd3de90d6c5e8187fedbcb0daf708da0f3..4559790678825eea856f3d6f9694ee6b10048c28 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,48 @@ >+2022-04-19 Simon Fraser <simon.fraser@apple.com> >+ >+ REGRESSION (r281913): Map toolbar flickers when dragging the map on https://gis.ee/ >+ https://bugs.webkit.org/show_bug.cgi?id=238589 >+ <rdar://90483049> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ If a layer has negative z-order descendants, and one of those descendants becomes >+ composited, then that layer also has to composite, because its foreground needs to render in >+ front of those descendants. But this is tricky, because the compositing toggle is >+ out-of-order; we only know that the layer has to get composited after processing >+ descendants. >+ >+ In particular, this created a problem with the overlap map, which tracks sets of rectangles >+ in "compositing scopes" via LayerOverlapMap. The delayed compositing toggle of the layer >+ with negative z-order descendants meant that any layers processed up to that point had their >+ bounds added in the wrong overlap scope. This resulted in subsequent bad overlap testing, >+ and a failure to make later layers composited. >+ >+ The previous fix in this area (r281913) was incorrect. Revert it, and do a better fix, which >+ is to speculatively push an overlap map entry for the layer with negative z-order >+ descendants, if necessary. If this layer ends up not getting composited, we unwind the >+ speculative push, which will merge that scope with its parent scope. >+ >+ In addition give OverlapMapContainer (an "overlap scope") a RenderLayer& which we can use >+ for logging, and to assert on correct behavior; it is not otherwise used in release builds. >+ >+ Tests: compositing/layer-creation/overlap-with-negative-z-layers.html >+ compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs.html >+ >+ * rendering/LayerOverlapMap.cpp: >+ (WebCore::OverlapMapContainer::OverlapMapContainer): >+ (WebCore::OverlapMapContainer::scopeLayer const): >+ (WebCore::OverlapMapContainer::dump const): >+ (WebCore::LayerOverlapMap::LayerOverlapMap): >+ (WebCore::LayerOverlapMap::add): >+ (WebCore::LayerOverlapMap::pushCompositingContainer): >+ (WebCore::LayerOverlapMap::popCompositingContainer): >+ * rendering/LayerOverlapMap.h: >+ * rendering/RenderLayerCompositor.cpp: >+ (WebCore::RenderLayerCompositor::computeCompositingRequirements): >+ (WebCore::RenderLayerCompositor::traverseUnchangedSubtree): >+ (WebCore::RenderLayerCompositor::updateOverlapMap const): >+ > 2022-04-18 Matt Woodrow <mattwoodrow@apple.com> > > Implement support for aligning baselines through subgrids >diff --git a/Source/WebCore/rendering/LayerOverlapMap.cpp b/Source/WebCore/rendering/LayerOverlapMap.cpp >index ae225c4564192e524d0c27568b225505b8bc80af..bfe362d03e7ad75827630dd7590baefad14493a5 100644 >--- a/Source/WebCore/rendering/LayerOverlapMap.cpp >+++ b/Source/WebCore/rendering/LayerOverlapMap.cpp >@@ -25,6 +25,7 @@ > > #include "config.h" > #include "LayerOverlapMap.h" >+#include "Logging.h" > #include "RenderLayer.h" > #include <wtf/text/TextStream.h> > >@@ -73,8 +74,9 @@ static TextStream& operator<<(TextStream& ts, const RectList& rectList) > class OverlapMapContainer { > WTF_MAKE_FAST_ALLOCATED; > public: >- OverlapMapContainer(const RenderLayer& rootLayer) >+ OverlapMapContainer(const RenderLayer& rootLayer, const RenderLayer& scopeLayer) > : m_rootScope(rootLayer) >+ , m_scopeLayer(scopeLayer) > { > } > >@@ -84,6 +86,8 @@ public: > void append(std::unique_ptr<OverlapMapContainer>&&); > > String dump(unsigned) const; >+ >+ const RenderLayer& scopeLayer() const { return m_scopeLayer; } > > private: > struct ClippingScope { >@@ -160,6 +164,7 @@ private: > ClippingScope& rootScope() { return m_rootScope; } > > ClippingScope m_rootScope; >+ const RenderLayer& m_scopeLayer; > }; > > void OverlapMapContainer::add(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) >@@ -258,7 +263,7 @@ String OverlapMapContainer::dump(unsigned indent) const > { > TextStream multilineStream; > multilineStream.increaseIndent(indent); >- multilineStream << "overlap container - root scope layer " << &m_rootScope.layer << " rects " << m_rootScope.rectList; >+ multilineStream << "overlap container - root layer " << &m_rootScope.layer << " scope layer " << &m_scopeLayer << " rects " << m_rootScope.rectList; > > for (auto& childScope : m_rootScope.children) > recursiveOutputToStream(multilineStream, childScope, 1); >@@ -273,7 +278,7 @@ LayerOverlapMap::LayerOverlapMap(const RenderLayer& rootLayer) > // Begin assuming the root layer will be composited so that there is > // something on the stack. The root layer should also never get an > // popCompositingContainer call. >- pushCompositingContainer(); >+ pushCompositingContainer(rootLayer); > } > > LayerOverlapMap::~LayerOverlapMap() = default; >@@ -284,8 +289,11 @@ void LayerOverlapMap::add(const RenderLayer& layer, const LayoutRect& bounds, co > // contribute to overlap as soon as their composited ancestor has been > // recursively processed and popped off the stack. > ASSERT(m_overlapStack.size() >= 2); >- m_overlapStack[m_overlapStack.size() - 2]->add(layer, bounds, enclosingClippingLayers); >- >+ auto& container = m_overlapStack[m_overlapStack.size() - 2]; >+ container->add(layer, bounds, enclosingClippingLayers); >+ >+ LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " contributes to overlap in the scope of layer " << &container->scopeLayer() << ", added to map " << *this); >+ > m_isEmpty = false; > } > >@@ -294,13 +302,14 @@ bool LayerOverlapMap::overlapsLayers(const RenderLayer& layer, const LayoutRect& > return m_overlapStack.last()->overlapsLayers(layer, bounds, enclosingClippingLayers); > } > >-void LayerOverlapMap::pushCompositingContainer() >+void LayerOverlapMap::pushCompositingContainer(const RenderLayer& layer) > { >- m_overlapStack.append(makeUnique<OverlapMapContainer>(m_rootLayer)); >+ m_overlapStack.append(makeUnique<OverlapMapContainer>(m_rootLayer, layer)); > } > >-void LayerOverlapMap::popCompositingContainer() >+void LayerOverlapMap::popCompositingContainer(const RenderLayer& layer) > { >+ ASSERT_UNUSED(layer, &m_overlapStack.last()->scopeLayer() == &layer); > m_overlapStack[m_overlapStack.size() - 2]->append(WTFMove(m_overlapStack.last())); > m_overlapStack.removeLast(); > } >diff --git a/Source/WebCore/rendering/LayerOverlapMap.h b/Source/WebCore/rendering/LayerOverlapMap.h >index e3061f0940a6629710cccdf3c6693380e63b4425..373d9ec721ccb6d2c547f08fc7ec71d7d62c78f0 100644 >--- a/Source/WebCore/rendering/LayerOverlapMap.h >+++ b/Source/WebCore/rendering/LayerOverlapMap.h >@@ -53,8 +53,8 @@ public: > bool overlapsLayers(const RenderLayer&, const LayoutRect&, const Vector<LayerAndBounds>& enclosingClippingLayers) const; > bool isEmpty() const { return m_isEmpty; } > >- void pushCompositingContainer(); >- void popCompositingContainer(); >+ void pushCompositingContainer(const RenderLayer&); >+ void popCompositingContainer(const RenderLayer&); > > const RenderGeometryMap& geometryMap() const { return m_geometryMap; } > RenderGeometryMap& geometryMap() { return m_geometryMap; } >diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp >index 2353c1770692f3d7135c2891ae683fa343387c36..2bda53dd3d73056724e797d15dc0facfddc28e14 100644 >--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp >+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp >@@ -1061,9 +1061,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor > layer.setIndirectCompositingReason(IndirectCompositingReason::Overlap); > LOG_WITH_STREAM(Compositing, stream << "layer " << &layer << " was sharing now will composite"); > } else { >- overlapMap.pushCompositingContainer(); >- didPushOverlapContainer = true; >- LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " will composite, pushed container " << overlapMap); >+ if (!didPushOverlapContainer) { >+ overlapMap.pushCompositingContainer(layer); >+ didPushOverlapContainer = true; >+ LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " will composite, pushed container " << overlapMap); >+ } > } > > willBeComposited = true; >@@ -1084,7 +1086,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor > layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation; > } else if (layerPaintsIntoProvidedBacking) { > currentState.backingSharingAncestor = &layer; >- overlapMap.pushCompositingContainer(); >+ overlapMap.pushCompositingContainer(layer); > didPushOverlapContainer = true; > LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " will share, pushed container " << overlapMap); > } >@@ -1098,18 +1100,33 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor > bool anyDescendantHas3DTransform = false; > bool descendantsAddedToOverlap = currentState.hasNonRootCompositedAncestor(); > >- unsigned newlyCompositedChildLayerCount = 0; >- for (auto* childLayer : layer.negativeZOrderLayers()) { >- computeCompositingRequirements(&layer, *childLayer, overlapMap, currentState, backingSharingState, anyDescendantHas3DTransform); >+ if (layer.hasNegativeZOrderLayers()) { >+ // Speculatively push this layer onto the overlap map. >+ bool didSpeculativelyPushOverlapContainer = false; >+ if (!didPushOverlapContainer) { >+ overlapMap.pushCompositingContainer(layer); >+ didPushOverlapContainer = true; >+ didSpeculativelyPushOverlapContainer = true; >+ } > >- // If we have to make a layer for this child, make one now so we can have a contents layer >- // (since we need to ensure that the -ve z-order child renders underneath our contents). >- if (!willBeComposited && currentState.subtreeIsCompositing) >- ++newlyCompositedChildLayerCount; >- } >- while (newlyCompositedChildLayerCount--) { >- layer.setIndirectCompositingReason(IndirectCompositingReason::BackgroundLayer); >- layerWillComposite(); >+ bool compositeForNegativeZOrderDescendant = false; >+ >+ for (auto* childLayer : layer.negativeZOrderLayers()) { >+ computeCompositingRequirements(&layer, *childLayer, overlapMap, currentState, backingSharingState, anyDescendantHas3DTransform); >+ >+ // If we have to make a layer for this child, make one now so we can have a contents layer >+ // (since we need to ensure that the -ve z-order child renders underneath our contents). >+ if (!willBeComposited && currentState.subtreeIsCompositing) { >+ layer.setIndirectCompositingReason(IndirectCompositingReason::BackgroundLayer); >+ layerWillComposite(); >+ compositeForNegativeZOrderDescendant = true; >+ } >+ } >+ >+ if (!compositeForNegativeZOrderDescendant && didSpeculativelyPushOverlapContainer) { >+ overlapMap.popCompositingContainer(layer); >+ didPushOverlapContainer = false; >+ } > } > > for (auto* childLayer : layer.normalFlowLayers()) >@@ -1246,7 +1263,7 @@ void RenderLayerCompositor::traverseUnchangedSubtree(RenderLayer* ancestorLayer, > // This layer now acts as the ancestor for kids. > currentState.compositingAncestor = &layer; > currentState.backingSharingAncestor = nullptr; >- overlapMap.pushCompositingContainer(); >+ overlapMap.pushCompositingContainer(layer); > didPushOverlapContainer = true; > LOG_WITH_STREAM(CompositingOverlap, stream << "unchangedSubtree: layer " << &layer << " will composite, pushed container " << overlapMap); > >@@ -1255,7 +1272,7 @@ void RenderLayerCompositor::traverseUnchangedSubtree(RenderLayer* ancestorLayer, > // Too hard to compute animated bounds if both us and some ancestor is animating transform. > layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation; > } else if (layerPaintsIntoProvidedBacking) { >- overlapMap.pushCompositingContainer(); >+ overlapMap.pushCompositingContainer(layer); > currentState.backingSharingAncestor = &layer; > didPushOverlapContainer = true; > LOG_WITH_STREAM(CompositingOverlap, stream << "unchangedSubtree: layer " << &layer << " will share, pushed container " << overlapMap); >@@ -2141,10 +2158,8 @@ void RenderLayerCompositor::addDescendantsToOverlapMapRecursive(LayerOverlapMap& > > void RenderLayerCompositor::updateOverlapMap(LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& layerExtent, bool didPushContainer, bool addLayerToOverlap, bool addDescendantsToOverlap) const > { >- if (addLayerToOverlap) { >+ if (addLayerToOverlap) > addToOverlapMap(overlapMap, layer, layerExtent); >- LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " contributes to overlap, added to map " << overlapMap); >- } > > if (addDescendantsToOverlap) { > // If this is the first non-root layer to composite, we need to add all the descendants we already traversed to the overlap map. >@@ -2153,7 +2168,7 @@ void RenderLayerCompositor::updateOverlapMap(LayerOverlapMap& overlapMap, const > } > > if (didPushContainer) { >- overlapMap.popCompositingContainer(); >+ overlapMap.popCompositingContainer(layer); > LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " is composited or shared, popped container " << overlapMap); > } > } >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index d9dc4aba0af91bdcb1d7689e60cf5710110597fd..e2d9b4f9fb70a3872f9ca2a7d968f85c2f5ed112 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,20 @@ >+2022-04-19 Simon Fraser <simon.fraser@apple.com> >+ >+ REGRESSION (r281913): Map toolbar flickers when dragging the map on https://gis.ee/ >+ https://bugs.webkit.org/show_bug.cgi?id=238589 >+ <rdar://90483049> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Move subtree-div-overlaps-multiple-negative-z-divs.html into the layer-creation directory. >+ Add a new test. >+ >+ * compositing/layer-creation/overlap-with-negative-z-layers-expected.html: Added. >+ * compositing/layer-creation/overlap-with-negative-z-layers.html: Added. >+ * compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs-expected.html: Renamed from LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs-expected.html. >+ * compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs.html: Renamed from LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs.html. >+ * fast/harness/render-tree-as-text-options-expected.txt: Test progressed; update results. >+ > 2022-04-18 Tim Nguyen <ntim@apple.com> > > [iOS] Skip CSS resize tests added by r292559 >diff --git a/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers-expected.html b/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..2aa2bbd4536100ccc2c09d9229bf8ce77685c6a3 >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers-expected.html >@@ -0,0 +1,49 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <style> >+ .wrapper { >+ position: absolute; >+ height: 400px; >+ width: 400px; >+ border: 1px solid black; >+ z-index: 0; >+ } >+ >+ .container { >+ position: absolute; >+ left: 0; >+ top: 0; >+ z-index: 0; >+ } >+ >+ .tile { >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ left: 100px; >+ top: 100px; >+ background-color: orange; >+ } >+ >+ .green { >+ position: relative; >+ width: 200px; >+ height: 200px; >+ margin: 10px; >+ background-color: green; >+ } >+ </style> >+</head> >+<body> >+ <p>The green box should be on top.</p> >+ <div class="wrapper"> >+ <div class="container" style="transform: translate3d(0px, 0px, 0px);"> >+ <div class="container"> >+ <div class="tile"></div> >+ </div> >+ </div> >+ <div class="green"></div> >+ </div> >+</body> >+</html> >diff --git a/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers.html b/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers.html >new file mode 100644 >index 0000000000000000000000000000000000000000..dea1a6299e8ffee0b7772302c1b50e8665fcb631 >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/overlap-with-negative-z-layers.html >@@ -0,0 +1,61 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <style> >+ .wrapper { >+ position: absolute; >+ height: 400px; >+ width: 400px; >+ border: 1px solid black; >+ z-index: 0; >+ } >+ >+ .container { >+ position: absolute; >+ left: 0; >+ top: 0; >+ z-index: 0; >+ } >+ >+ .negative { >+ position: absolute; >+ width: 20px; >+ height: 20px; >+ background-color: darkred; >+ } >+ >+ .tile { >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ left: 100px; >+ top: 100px; >+ background-color: orange; >+ } >+ >+ .green { >+ position: relative; >+ width: 200px; >+ height: 200px; >+ margin: 10px; >+ background-color: green; >+ } >+ </style> >+</head> >+<body> >+ <p>The green box should be on top.</p> >+ <div class="wrapper"> >+ <div class="container" style="transform: translate3d(0px, 0px, 0px);"> >+ <div class="container"> >+ <div class="tile"></div> >+ </div> >+ <div class="container"> >+ <div class="negative" style="transform: translate3d(50px, 50px, 0px); z-index: -3;"></div> >+ <div class="negative" style="transform: translate3d(50px, 100px, 0px); z-index: -2;"></div> >+ <div class="negative" style="transform: translate3d(50px, 150px, 0px); z-index: -1;"></div> >+ </div> >+ </div> >+ <div class="green"></div> >+ </div> >+</body> >+</html> >diff --git a/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs-expected.html b/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3129daefb1ab0d6410fc7f5d9426a7a6b6aa00a8 >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs-expected.html >@@ -0,0 +1,2 @@ >+<!DOCTYPE html> >+<div style="background:green;width:100px;height:100px"></div> >diff --git a/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs.html b/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs.html >new file mode 100644 >index 0000000000000000000000000000000000000000..df9df240741a0c5083e0f4f0a14322677d2539a0 >--- /dev/null >+++ b/LayoutTests/compositing/layer-creation/subtree-div-overlaps-multiple-negative-z-divs.html >@@ -0,0 +1,27 @@ >+<!DOCTYPE html> >+<style> >+.negative { >+ z-index: -1; >+} >+.abs { >+ position: absolute; >+} >+.green { >+ width: 100px; >+ height: 100px; >+ background-color: green; >+} >+ >+.red { >+ width: 100px; >+ height: 100px; >+ background-color: red; >+ will-change: transform; >+} >+</style> >+<body> >+<div class="negative abs"> >+ <div class="red"></div> >+</div> >+<div class="negative abs green"></div> >+</body> >diff --git a/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs-expected.html b/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs-expected.html >deleted file mode 100644 >index 3129daefb1ab0d6410fc7f5d9426a7a6b6aa00a8..0000000000000000000000000000000000000000 >--- a/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs-expected.html >+++ /dev/null >@@ -1,2 +0,0 @@ >-<!DOCTYPE html> >-<div style="background:green;width:100px;height:100px"></div> >diff --git a/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs.html b/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs.html >deleted file mode 100644 >index df9df240741a0c5083e0f4f0a14322677d2539a0..0000000000000000000000000000000000000000 >--- a/LayoutTests/compositing/subtree-div-overlaps-multiple-negative-z-divs.html >+++ /dev/null >@@ -1,27 +0,0 @@ >-<!DOCTYPE html> >-<style> >-.negative { >- z-index: -1; >-} >-.abs { >- position: absolute; >-} >-.green { >- width: 100px; >- height: 100px; >- background-color: green; >-} >- >-.red { >- width: 100px; >- height: 100px; >- background-color: red; >- will-change: transform; >-} >-</style> >-<body> >-<div class="negative abs"> >- <div class="red"></div> >-</div> >-<div class="negative abs green"></div> >-</body> >diff --git a/LayoutTests/fast/harness/render-tree-as-text-options-expected.txt b/LayoutTests/fast/harness/render-tree-as-text-options-expected.txt >index 0d91f5dd84f9506b43032b5609c7a1a6614f7773..d9945c7cdea7ee31ed90615a835445158f80e9bd 100644 >--- a/LayoutTests/fast/harness/render-tree-as-text-options-expected.txt >+++ b/LayoutTests/fast/harness/render-tree-as-text-options-expected.txt >@@ -14,5 +14,5 @@ layer at (0,0) size 800x600 (composited [root], bounds=at (0,0) size 800x600, dr > RenderSVGRect {rect} at (18,278) size 100x100 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=20.00] [width=100.00] [height=100.00] > RenderText {#text} at (0,0) size 0x0 > positive z-order list (1) >- layer at (8,8) size 200x400 >+ layer at (8,8) size 200x400 (composited [overlap], bounds=at (0,0) size 200x400, drawsContent=0, paints into ancestor=0) > RenderBlock (relative positioned) zI: 1 {DIV} at (0,0) size 200x400
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 238589
:
457855
|
457958
|
457961
| 458008