summaryrefslogtreecommitdiffstats
path: root/layout
diff options
context:
space:
mode:
Diffstat (limited to 'layout')
-rw-r--r--layout/base/RestyleManagerBase.cpp63
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp19
-rw-r--r--layout/base/nsCaret.cpp4
-rw-r--r--layout/base/nsChangeHint.h55
-rw-r--r--layout/base/nsDocumentViewer.cpp13
-rw-r--r--layout/base/nsIDocumentViewerPrint.h2
-rw-r--r--layout/base/nsIPresShell.h14
-rw-r--r--layout/base/nsLayoutDebugger.cpp6
-rw-r--r--layout/base/nsLayoutUtils.cpp153
-rw-r--r--layout/base/nsLayoutUtils.h5
-rw-r--r--layout/base/nsPresContext.cpp12
-rw-r--r--layout/base/nsPresContext.h22
-rw-r--r--layout/base/nsPresShell.cpp144
-rw-r--r--layout/base/tests/bug1078327_inner.html8
-rw-r--r--layout/base/tests/bug1162990_inner_1.html4
-rw-r--r--layout/base/tests/bug1162990_inner_2.html2
-rw-r--r--layout/base/tests/bug976963_inner.html241
-rw-r--r--layout/base/tests/bug977003_inner_5.html8
-rw-r--r--layout/base/tests/bug977003_inner_6.html6
-rw-r--r--layout/base/tests/mochitest.ini2
-rw-r--r--layout/base/tests/test_bug976963.html35
-rw-r--r--layout/forms/nsDateTimeControlFrame.cpp3
-rw-r--r--layout/forms/nsFieldSetFrame.cpp71
-rw-r--r--layout/forms/nsFieldSetFrame.h10
-rw-r--r--layout/forms/nsHTMLButtonControlFrame.cpp41
-rw-r--r--layout/forms/nsHTMLButtonControlFrame.h7
-rw-r--r--layout/forms/nsLegendFrame.h5
-rw-r--r--layout/forms/nsTextControlFrame.cpp11
-rw-r--r--layout/forms/nsTextControlFrame.h35
-rw-r--r--layout/forms/test/test_bug562447.html6
-rw-r--r--layout/forms/test/test_bug564115.html4
-rw-r--r--layout/generic/ReflowInput.cpp12
-rw-r--r--layout/generic/ReflowInput.h4
-rw-r--r--layout/generic/Selection.h3
-rw-r--r--layout/generic/nsFlexContainerFrame.cpp155
-rw-r--r--layout/generic/nsFlexContainerFrame.h15
-rw-r--r--layout/generic/nsFrame.cpp2
-rw-r--r--layout/generic/nsGridContainerFrame.cpp109
-rw-r--r--layout/generic/nsIFrame.h8
-rw-r--r--layout/generic/nsSelection.cpp12
-rw-r--r--layout/generic/nsTextFrame.cpp6
-rw-r--r--layout/printing/nsPagePrintTimer.cpp10
-rw-r--r--layout/reftests/bugs/315920-17.html15
-rw-r--r--layout/reftests/css-grid/grid-auto-min-sizing-min-content-min-size-004-ref.html2
-rw-r--r--layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-004-ref.html2
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-001-ref.html78
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-001.html74
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-002-ref.html79
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-002.html75
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-003-ref.html84
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-003.html75
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-004-ref.html88
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-004.html82
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-005-ref.html83
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-005.html77
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html54
-rw-r--r--layout/reftests/css-grid/grid-item-overflow-stretch-006.html56
-rw-r--r--layout/reftests/css-grid/grid-min-content-min-sizing-transferred-size-004-ref.html2
-rw-r--r--layout/reftests/css-grid/reftest.list6
-rw-r--r--layout/reftests/forms/display-block-baselines-1-ref.html91
-rw-r--r--layout/reftests/forms/display-block-baselines-1.html92
-rw-r--r--layout/reftests/forms/display-block-baselines-2-ref.html100
-rw-r--r--layout/reftests/forms/display-block-baselines-2.html100
-rw-r--r--layout/reftests/forms/display-block-baselines-3-ref.html72
-rw-r--r--layout/reftests/forms/display-block-baselines-3.html73
-rw-r--r--layout/reftests/forms/display-block-baselines-4-ref.html73
-rw-r--r--layout/reftests/forms/display-block-baselines-4.html74
-rw-r--r--layout/reftests/forms/display-block-baselines-5-ref.html72
-rw-r--r--layout/reftests/forms/display-block-baselines-5.html72
-rw-r--r--layout/reftests/forms/input/datetime/reftest.list11
-rw-r--r--layout/reftests/forms/input/datetime/time-content-left-aligned-ref.html9
-rw-r--r--layout/reftests/forms/input/datetime/time-content-left-aligned.html9
-rw-r--r--layout/reftests/forms/input/datetime/time-reset-button-right-aligned-ref.html9
-rw-r--r--layout/reftests/forms/input/datetime/time-reset-button-right-aligned.html10
-rw-r--r--layout/reftests/forms/input/datetime/time-small-height-ref.html18
-rw-r--r--layout/reftests/forms/input/datetime/time-small-height.html19
-rw-r--r--layout/reftests/forms/input/datetime/time-small-width-height-ref.html18
-rw-r--r--layout/reftests/forms/input/datetime/time-small-width-height.html19
-rw-r--r--layout/reftests/forms/input/datetime/time-small-width-ref.html19
-rw-r--r--layout/reftests/forms/input/datetime/time-small-width.html20
-rw-r--r--layout/reftests/forms/reftest.list5
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-1-ref.html18
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-1a.html23
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-1b.html23
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-1c.html19
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2-ref.html15
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2a.html26
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2b.html26
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2c.html24
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2d.html24
-rw-r--r--layout/reftests/scrolling/propagated-overflow-style-2e.html15
-rw-r--r--layout/reftests/scrolling/reftest.list10
-rw-r--r--layout/reftests/svg/radialGradient-fr-01.svg27
-rw-r--r--layout/reftests/svg/radialGradient-fr-02-ref.svg28
-rw-r--r--layout/reftests/svg/radialGradient-fr-02.svg27
-rw-r--r--layout/reftests/svg/reftest.list2
-rw-r--r--layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001-ref.html16
-rw-r--r--layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001.html47
-rw-r--r--layout/reftests/w3c-css/submitted/flexbox/reftest.list2
-rw-r--r--layout/reftests/xul/css-flex-1-ref.html18
-rw-r--r--layout/reftests/xul/css-flex-1.xul153
-rw-r--r--layout/reftests/xul/reftest.list2
-rw-r--r--layout/style/FontFaceSet.cpp12
-rw-r--r--layout/style/nsCSSKeywordList.h2
-rw-r--r--layout/style/nsCSSParser.cpp7
-rw-r--r--layout/style/nsCSSProps.cpp2
-rw-r--r--layout/style/nsCSSPseudoElements.h3
-rw-r--r--layout/style/nsCSSRuleProcessor.cpp10
-rw-r--r--layout/style/nsLayoutStylesheetCache.cpp293
-rw-r--r--layout/style/nsMediaFeatures.cpp18
-rw-r--r--layout/style/nsRuleNode.cpp3
-rw-r--r--layout/style/nsStyleStruct.cpp23
-rw-r--r--layout/style/nsStyleStruct.h11
-rw-r--r--layout/style/res/forms.css5
-rw-r--r--layout/style/res/html.css5
-rw-r--r--layout/style/test/chrome/bug418986-2.js2
-rw-r--r--layout/style/test/mochitest.ini1
-rw-r--r--layout/style/test/property_database.js14
-rw-r--r--layout/style/test/test_dynamic_change_causing_reflow.html107
-rw-r--r--layout/style/test/test_media_queries.html7
-rw-r--r--layout/style/test/test_viewport_scrollbar_causing_reflow.html125
-rw-r--r--layout/svg/SVGTextFrame.cpp4
-rw-r--r--layout/svg/nsSVGGradientFrame.cpp5
-rw-r--r--layout/svg/nsSVGUtils.cpp3
-rw-r--r--layout/tools/recording/recording-cmdline.js4
125 files changed, 3610 insertions, 865 deletions
diff --git a/layout/base/RestyleManagerBase.cpp b/layout/base/RestyleManagerBase.cpp
index 9a5ce43eb..d96d9dbbb 100644
--- a/layout/base/RestyleManagerBase.cpp
+++ b/layout/base/RestyleManagerBase.cpp
@@ -154,7 +154,7 @@ RestyleManagerBase::ChangeHintToString(nsChangeHint aHint)
"NeutralChange", "InvalidateRenderingObservers",
"ReflowChangesSizeOrPosition", "UpdateComputedBSize",
"UpdateUsesOpacity", "UpdateBackgroundPosition",
- "AddOrRemoveTransform"
+ "AddOrRemoveTransform", "CSSOverflowChange",
};
static_assert(nsChangeHint_AllHints == (1 << ArrayLength(names)) - 1,
"Name list doesn't match change hints.");
@@ -1070,6 +1070,67 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
FramePropertyTable* propTable = presContext->PropertyTable();
nsCSSFrameConstructor* frameConstructor = presContext->FrameConstructor();
+ // Handle nsChangeHint_CSSOverflowChange, by either updating the
+ // scrollbars on the viewport, or upgrading the change hint to frame-reconstruct.
+ for (nsStyleChangeData& data : aChangeList) {
+ if (data.mHint & nsChangeHint_CSSOverflowChange) {
+ data.mHint &= ~nsChangeHint_CSSOverflowChange;
+ bool doReconstruct = true; // assume the worst
+
+ // Only bother with this if we're html/body, since:
+ // (a) It'd be *expensive* to reframe these particular nodes. They're
+ // at the root, so reframing would mean rebuilding the world.
+ // (b) It's often *unnecessary* to reframe for "overflow" changes on
+ // these particular nodes. In general, the only reason we reframe
+ // for "overflow" changes is so we can construct (or destroy) a
+ // scrollframe & scrollbars -- and the html/body nodes often don't
+ // need their own scrollframe/scrollbars because they coopt the ones
+ // on the viewport (which always exist). So depending on whether
+ // that's happening, we can skip the reframe for these nodes.
+ if (data.mContent->IsAnyOfHTMLElements(nsGkAtoms::body,
+ nsGkAtoms::html)) {
+ // If the restyled element provided/provides the scrollbar styles for
+ // the viewport before and/or after this restyle, AND it's not coopting
+ // that responsibility from some other element (which would need
+ // reconstruction to make its own scrollframe now), THEN: we don't need
+ // to reconstruct - we can just reflow, because no scrollframe is being
+ // added/removed.
+ nsIContent* prevOverrideNode =
+ presContext->GetViewportScrollbarStylesOverrideNode();
+ nsIContent* newOverrideNode =
+ presContext->UpdateViewportScrollbarStylesOverride();
+
+ if (data.mContent == prevOverrideNode ||
+ data.mContent == newOverrideNode) {
+ // If we get here, the restyled element provided the scrollbar styles
+ // for viewport before this restyle, OR it will provide them after.
+ if (!prevOverrideNode || !newOverrideNode ||
+ prevOverrideNode == newOverrideNode) {
+ // If we get here, the restyled element is NOT replacing (or being
+ // replaced by) some other element as the viewport's
+ // scrollbar-styles provider. (If it were, we'd potentially need to
+ // reframe to create a dedicated scrollframe for whichever element
+ // is being booted from providing viewport scrollbar styles.)
+ //
+ // Under these conditions, we're OK to assume that this "overflow"
+ // change only impacts the root viewport's scrollframe, which
+ // already exists, so we can simply reflow instead of reframing.
+ // When requesting this reflow, we send the exact same change hints
+ // that "width" and "height" would send (since conceptually,
+ // adding/removing scrollbars is like changing the available
+ // space).
+ data.mHint |= (nsChangeHint_ReflowHintsForISizeChange |
+ nsChangeHint_ReflowHintsForBSizeChange);
+ doReconstruct = false;
+ }
+ }
+ }
+ if (doReconstruct) {
+ data.mHint |= nsChangeHint_ReconstructFrame;
+ }
+ }
+ }
+
// Make sure to not rebuild quote or counter lists while we're
// processing restyles
frameConstructor->BeginUpdate();
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index a118c38f9..767298b85 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3658,13 +3658,13 @@ nsCSSFrameConstructor::FindInputData(Element* aElement,
nsCSSAnonBoxes::buttonContent) },
// TODO: this is temporary until a frame is written: bug 635240.
SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame),
- // TODO: this is temporary until a frame is written: bug 888320.
- SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
// On Android/B2G, date/time input appears as a normal text box.
SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame),
+ SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
#else
SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame),
+ SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame),
#endif
// TODO: this is temporary until a frame is written: bug 888320
SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame),
@@ -8246,11 +8246,19 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
*aDestroyedFramesFor = aChild;
}
+ nsPresContext* presContext = mPresShell->GetPresContext();
+ MOZ_ASSERT(presContext, "Our presShell should have a valid presContext");
+
if (aChild->IsHTMLElement(nsGkAtoms::body) ||
(!aContainer && aChild->IsElement())) {
- // This might be the element we propagated viewport scrollbar
- // styles from. Recompute those.
- mPresShell->GetPresContext()->UpdateViewportScrollbarStylesOverride();
+ // We might be removing the element that we propagated viewport scrollbar
+ // styles from. Recompute those. (This clause covers two of the three
+ // possible scrollbar-propagation sources: the <body> [as aChild or a
+ // descendant] and the root node. The other possible scrollbar-propagation
+ // source is a fullscreen element, and we have code elsewhere to update
+ // scrollbars after fullscreen elements are removed -- specifically, it's
+ // part of the fullscreen cleanup code called by Element::UnbindFromTree.)
+ presContext->UpdateViewportScrollbarStylesOverride();
}
// XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
@@ -8316,7 +8324,6 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
ClearDisplayContentsIn(aChild, aContainer);
}
- nsPresContext* presContext = mPresShell->GetPresContext();
#ifdef MOZ_XUL
if (NotifyListBoxBody(presContext, aContainer, aChild, aOldNextSibling,
childFrame, CONTENT_REMOVED)) {
diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp
index 2f08d156e..8ad435950 100644
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -200,8 +200,8 @@ nsCaret::ComputeMetrics(nsIFrame* aFrame, int32_t aOffset, nscoord aCaretHeight)
// between 0 and 1 goes up to 1 so we don't let the caret disappear.
int32_t tpp = aFrame->PresContext()->AppUnitsPerDevPixel();
Metrics result;
- result.mCaretWidth = NS_ROUND_BORDER_TO_PIXELS(caretWidth, tpp);
- result.mBidiIndicatorSize = NS_ROUND_BORDER_TO_PIXELS(bidiIndicatorSize, tpp);
+ result.mCaretWidth = NS_ROUND_CARET_TO_PIXELS(caretWidth, tpp);
+ result.mBidiIndicatorSize = NS_ROUND_CARET_TO_PIXELS(bidiIndicatorSize, tpp);
return result;
}
diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h
index 318b84840..eb2709de6 100644
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -217,6 +217,16 @@ enum nsChangeHint {
*/
nsChangeHint_AddOrRemoveTransform = 1 << 27,
+ /**
+ * Indicates that the overflow-x and/or overflow-y property changed.
+ *
+ * In most cases, this is equivalent to nsChangeHint_ReconstructFrame. But
+ * in some special cases where the change is really targeting the viewport's
+ * scrollframe, this is instead equivalent to nsChangeHint_AllReflowHints
+ * (because the viewport always has an associated scrollframe).
+ */
+ nsChangeHint_CSSOverflowChange = 1 << 28,
+
// IMPORTANT NOTE: When adding new hints, consider whether you need
// to add them to NS_HintsNotHandledForDescendantsIn() below. Please
// also add them to RestyleManager::ChangeHintToString and modify
@@ -225,7 +235,7 @@ enum nsChangeHint {
/**
* Dummy hint value for all hints. It exists for compile time check.
*/
- nsChangeHint_AllHints = (1 << 28) - 1,
+ nsChangeHint_AllHints = (1 << 29) - 1,
};
// Redefine these operators to return nothing. This will catch any use
@@ -306,6 +316,7 @@ inline nsChangeHint operator^=(nsChangeHint& aLeft, nsChangeHint aRight)
nsChangeHint_UpdatePostTransformOverflow | \
nsChangeHint_UpdateParentOverflow | \
nsChangeHint_ChildrenOnlyTransform | \
+ nsChangeHint_CSSOverflowChange | \
nsChangeHint_RecomputePosition | \
nsChangeHint_UpdateContainingBlock | \
nsChangeHint_AddOrRemoveTransform | \
@@ -374,6 +385,48 @@ inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint)
nsChangeHint_ClearAncestorIntrinsics | \
nsChangeHint_ClearDescendantIntrinsics | \
nsChangeHint_NeedDirtyReflow)
+
+// Below are the change hints that we send for ISize & BSize changes.
+// Each is similar to nsChangeHint_AllReflowHints with a few changes.
+
+// * For an ISize change, we send nsChangeHint_AllReflowHints, with two bits
+// excluded: nsChangeHint_ClearDescendantIntrinsics (because an ancestor's
+// inline-size change can't affect descendant intrinsic sizes), and
+// nsChangeHint_NeedDirtyReflow (because ISize changes don't need to *force*
+// all descendants to reflow).
+#define nsChangeHint_ReflowHintsForISizeChange \
+ nsChangeHint(nsChangeHint_AllReflowHints & \
+ ~(nsChangeHint_ClearDescendantIntrinsics | \
+ nsChangeHint_NeedDirtyReflow))
+
+// * For a BSize change, we send almost the same hints as for ISize changes,
+// with one extra: nsChangeHint_UpdateComputedBSize. We need this hint because
+// BSize changes CAN affect descendant intrinsic sizes, due to replaced
+// elements with percentage BSizes in descendants which also have percentage
+// BSizes. nsChangeHint_UpdateComputedBSize clears intrinsic sizes for frames
+// that have such replaced elements. (We could instead send
+// nsChangeHint_ClearDescendantIntrinsics, but that's broader than we need.)
+//
+// NOTE: You might think that BSize changes could exclude
+// nsChangeHint_ClearAncestorIntrinsics (which is inline-axis specific), but we
+// do need to send it, to clear cached results from CSS Flex measuring reflows.
+#define nsChangeHint_ReflowHintsForBSizeChange \
+ nsChangeHint((nsChangeHint_AllReflowHints | \
+ nsChangeHint_UpdateComputedBSize) & \
+ ~(nsChangeHint_ClearDescendantIntrinsics | \
+ nsChangeHint_NeedDirtyReflow))
+
+// * For changes to the float area of an already-floated element, we need all
+// reflow hints, but not the ones that apply to descendants.
+// Our descendants aren't impacted when our float area only changes
+// placement but not size/shape. (e.g. if we change which side we float to).
+// But our ancestors/siblings are potentially impacted, so we need to send
+// the non-descendant reflow hints.
+#define nsChangeHint_ReflowHintsForFloatAreaChange \
+ nsChangeHint(nsChangeHint_AllReflowHints & \
+ ~(nsChangeHint_ClearDescendantIntrinsics | \
+ nsChangeHint_NeedDirtyReflow))
+
#define NS_STYLE_HINT_REFLOW \
nsChangeHint(NS_STYLE_HINT_VISUAL | nsChangeHint_AllReflowHints)
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
index a1105ae52..137efb3cd 100644
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -544,6 +544,12 @@ nsDocumentViewer::~nsDocumentViewer()
mDocument->Destroy();
}
+ if (mPrintEngine) {
+ mPrintEngine->Destroy();
+ mPrintEngine = nullptr;
+ }
+
+ MOZ_RELEASE_ASSERT(mDestroyRefCount == 0);
NS_ASSERTION(!mPresShell && !mPresContext,
"User did not call nsIContentViewer::Destroy");
if (mPresShell || mPresContext) {
@@ -1611,7 +1617,6 @@ nsDocumentViewer::Destroy()
// We also keep the viewer from being cached in session history, since
// we require all documents there to be sanitized.
if (mDestroyRefCount != 0) {
- --mDestroyRefCount;
return NS_OK;
}
@@ -4420,6 +4425,12 @@ nsDocumentViewer::IncrementDestroyRefCount()
++mDestroyRefCount;
}
+void
+nsDocumentViewer::DecrementDestroyRefCount()
+{
+ --mDestroyRefCount;
+}
+
//------------------------------------------------------------
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
diff --git a/layout/base/nsIDocumentViewerPrint.h b/layout/base/nsIDocumentViewerPrint.h
index 8bc2465a1..e3c397f3a 100644
--- a/layout/base/nsIDocumentViewerPrint.h
+++ b/layout/base/nsIDocumentViewerPrint.h
@@ -41,6 +41,7 @@ public:
virtual mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) = 0;
virtual void IncrementDestroyRefCount() = 0;
+ virtual void DecrementDestroyRefCount() = 0;
virtual void ReturnToGalleyPresentation() = 0;
@@ -75,6 +76,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
bool GetIsPrintPreview() override; \
mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) override; \
void IncrementDestroyRefCount() override; \
+ void DecrementDestroyRefCount() override; \
void ReturnToGalleyPresentation() override; \
void OnDonePrinting() override; \
bool IsInitializedForPrintPreview() override; \
diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h
index cbbae0e8f..5990402ed 100644
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1298,11 +1298,11 @@ public:
}
};
- static void DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture,
- uint32_t aPointerId,
- uint16_t aPointerType,
- bool aIsPrimary,
- nsIContent* aCaptureTarget);
+ static void DispatchGotOrLostPointerCaptureEvent(
+ bool aIsGotCapture,
+ const mozilla::WidgetPointerEvent* aPointerEvent,
+ nsIContent* aCaptureTarget);
+
static PointerCaptureInfo* GetPointerCaptureInfo(uint32_t aPointerId);
static void SetPointerCapturingContent(uint32_t aPointerId,
nsIContent* aContent);
@@ -1311,8 +1311,8 @@ public:
// CheckPointerCaptureState checks cases, when got/lostpointercapture events
// should be fired.
- static void CheckPointerCaptureState(uint32_t aPointerId,
- uint16_t aPointerType, bool aIsPrimary);
+ static void CheckPointerCaptureState(
+ const mozilla::WidgetPointerEvent* aPointerEvent);
// GetPointerInfo returns true if pointer with aPointerId is situated in
// device, false otherwise.
diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp
index 22c313c72..6ce629bc9 100644
--- a/layout/base/nsLayoutDebugger.cpp
+++ b/layout/base/nsLayoutDebugger.cpp
@@ -126,8 +126,10 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
contentData.AppendLiteral(" id:");
contentData.Append(tmp);
}
- if (content->GetClasses()) {
- content->GetClasses()->ToString(tmp);
+ const nsAttrValue* classes = content->IsElement() ?
+ content->AsElement()->GetClasses() : nullptr;
+ if (classes) {
+ classes->ToString(tmp);
contentData.AppendLiteral(" class:");
contentData.Append(tmp);
}
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index ed34f39ce..c8c91b251 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4637,6 +4637,63 @@ GetPercentBSize(const nsStyleCoord& aStyle,
return true;
}
+// Return true if aStyle can be resolved to a definite value and if so
+// return that value in aResult.
+static bool
+GetDefiniteSize(const nsStyleCoord& aStyle,
+ nsIFrame* aFrame,
+ bool aIsInlineAxis,
+ const Maybe<LogicalSize>& aPercentageBasis,
+ nscoord* aResult)
+{
+ switch (aStyle.GetUnit()) {
+ case eStyleUnit_Coord:
+ *aResult = aStyle.GetCoordValue();
+ return true;
+ case eStyleUnit_Percent: {
+ if (aPercentageBasis.isNothing()) {
+ return false;
+ }
+ auto wm = aFrame->GetWritingMode();
+ nscoord pb = aIsInlineAxis ? aPercentageBasis.value().ISize(wm)
+ : aPercentageBasis.value().BSize(wm);
+ if (pb != NS_UNCONSTRAINEDSIZE) {
+ nscoord p = NSToCoordFloorClamped(pb * aStyle.GetPercentValue());
+ *aResult = std::max(nscoord(0), p);
+ return true;
+ }
+ return false;
+ }
+ case eStyleUnit_Calc: {
+ nsStyleCoord::Calc* calc = aStyle.GetCalcValue();
+ if (calc->mPercent != 0.0f) {
+ if (aPercentageBasis.isNothing()) {
+ return false;
+ }
+ auto wm = aFrame->GetWritingMode();
+ nscoord pb = aIsInlineAxis ? aPercentageBasis.value().ISize(wm)
+ : aPercentageBasis.value().BSize(wm);
+ if (pb == NS_UNCONSTRAINEDSIZE) {
+ // XXXmats given that we're calculating an intrinsic size here,
+ // maybe we should back-compute the calc-size using AddPercents?
+ return false;
+ }
+ *aResult = std::max(0, calc->mLength +
+ NSToCoordFloorClamped(pb * calc->mPercent));
+ } else {
+ *aResult = std::max(0, calc->mLength);
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+//
+// NOTE: this function will be replaced by GetDefiniteSizeTakenByBoxSizing (bug 1363918).
+// Please do not add new uses of this function.
+//
// Get the amount of vertical space taken out of aFrame's content area due to
// its borders and paddings given the box-sizing value in aBoxSizing. We don't
// get aBoxSizing from the frame because some callers want to compute this for
@@ -4681,6 +4738,54 @@ GetBSizeTakenByBoxSizing(StyleBoxSizing aBoxSizing,
return bSizeTakenByBoxSizing;
}
+// Get the amount of space taken out of aFrame's content area due to its
+// borders and paddings given the box-sizing value in aBoxSizing. We don't
+// get aBoxSizing from the frame because some callers want to compute this for
+// specific box-sizing values.
+// aIsInlineAxis is true if we're computing for aFrame's inline axis.
+// aIgnorePadding is true if padding should be ignored.
+static nscoord
+GetDefiniteSizeTakenByBoxSizing(StyleBoxSizing aBoxSizing,
+ nsIFrame* aFrame,
+ bool aIsInlineAxis,
+ bool aIgnorePadding,
+ const Maybe<LogicalSize>& aPercentageBasis)
+{
+ nscoord sizeTakenByBoxSizing = 0;
+ if (MOZ_UNLIKELY(aBoxSizing == StyleBoxSizing::Border)) {
+ const bool isHorizontalAxis =
+ aIsInlineAxis == !aFrame->GetWritingMode().IsVertical();
+ const nsStyleBorder* styleBorder = aFrame->StyleBorder();
+ sizeTakenByBoxSizing =
+ isHorizontalAxis ? styleBorder->GetComputedBorder().LeftRight()
+ : styleBorder->GetComputedBorder().TopBottom();
+ if (!aIgnorePadding) {
+ const nsStyleSides& stylePadding = aFrame->StylePadding()->mPadding;
+ const nsStyleCoord& pStart =
+ stylePadding.Get(isHorizontalAxis ? eSideLeft : eSideTop);
+ const nsStyleCoord& pEnd =
+ stylePadding.Get(isHorizontalAxis ? eSideRight : eSideBottom);
+ nscoord pad;
+ // XXXbz Calling GetPercentBSize on padding values looks bogus, since
+ // percent padding is always a percentage of the inline-size of the
+ // containing block. We should perhaps just treat non-absolute paddings
+ // here as 0 instead, except that in some cases the width may in fact be
+ // known. See bug 1231059.
+ if (GetDefiniteSize(pStart, aFrame, aIsInlineAxis, aPercentageBasis, &pad) ||
+ (aPercentageBasis.isNothing() &&
+ GetPercentBSize(pStart, aFrame, isHorizontalAxis, pad))) {
+ sizeTakenByBoxSizing += pad;
+ }
+ if (GetDefiniteSize(pEnd, aFrame, aIsInlineAxis, aPercentageBasis, &pad) ||
+ (aPercentageBasis.isNothing() &&
+ GetPercentBSize(pEnd, aFrame, isHorizontalAxis, pad))) {
+ sizeTakenByBoxSizing += pad;
+ }
+ }
+ }
+ return sizeTakenByBoxSizing;
+}
+
// Handles only -moz-max-content and -moz-min-content, and
// -moz-fit-content for min-width and max-width, since the others
// (-moz-fit-content for width, and -moz-available) have no effect on
@@ -4940,17 +5045,21 @@ AddStateBitToAncestors(nsIFrame* aFrame, nsFrameState aBit)
}
/* static */ nscoord
-nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
- nsRenderingContext* aRenderingContext,
- nsIFrame* aFrame,
- IntrinsicISizeType aType,
- uint32_t aFlags,
- nscoord aMarginBoxMinSizeClamp)
+nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
+ nsRenderingContext* aRenderingContext,
+ nsIFrame* aFrame,
+ IntrinsicISizeType aType,
+ const Maybe<LogicalSize>& aPercentageBasis,
+ uint32_t aFlags,
+ nscoord aMarginBoxMinSizeClamp)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(aFrame->GetParent(),
"IntrinsicForAxis called on frame not in tree");
NS_PRECONDITION(aType == MIN_ISIZE || aType == PREF_ISIZE, "bad type");
+ MOZ_ASSERT(aFrame->GetParent()->Type() != LayoutFrameType::GridContainer ||
+ aPercentageBasis.isSome(),
+ "grid layout should always pass a percentage basis");
const bool horizontalAxis = MOZ_LIKELY(aAxis == eAxisHorizontal);
#ifdef DEBUG_INTRINSIC_WIDTH
@@ -5014,6 +5123,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
PhysicalAxis ourInlineAxis =
aFrame->GetWritingMode().PhysicalAxis(eLogicalAxisInline);
+ const bool isInlineAxis = aAxis == ourInlineAxis;
// If we have a specified width (or a specified 'min-width' greater
// than the specified 'max-width', which works out to the same thing),
// don't even bother getting the frame's intrinsic width, because in
@@ -5043,7 +5153,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
// constraint is the max-content contribution which we shouldn't clamp.
aMarginBoxMinSizeClamp = NS_MAXSIZE;
}
- if (MOZ_UNLIKELY(aAxis != ourInlineAxis)) {
+ if (MOZ_UNLIKELY(!isInlineAxis)) {
IntrinsicSize intrinsicSize = aFrame->GetIntrinsicSize();
const nsStyleCoord intrinsicBCoord =
horizontalAxis ? intrinsicSize.width : intrinsicSize.height;
@@ -5105,21 +5215,23 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
nscoord bSizeTakenByBoxSizing =
- GetBSizeTakenByBoxSizing(boxSizing, aFrame, horizontalAxis,
- aFlags & IGNORE_PADDING);
-
+ GetDefiniteSizeTakenByBoxSizing(boxSizing, aFrame, !isInlineAxis,
+ aFlags & IGNORE_PADDING,
+ aPercentageBasis);
// NOTE: This is only the minContentSize if we've been passed MIN_INTRINSIC_ISIZE
// (which is fine, because this should only be used inside a check for that flag).
nscoord minContentSize = result;
nscoord h;
- if (GetAbsoluteCoord(styleBSize, h) ||
- GetPercentBSize(styleBSize, aFrame, horizontalAxis, h)) {
+ if (GetDefiniteSize(styleBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) ||
+ (aPercentageBasis.isNothing() &&
+ GetPercentBSize(styleBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing);
result = NSCoordMulDiv(h, ratioISize, ratioBSize);
}
- if (GetAbsoluteCoord(styleMaxBSize, h) ||
- GetPercentBSize(styleMaxBSize, aFrame, horizontalAxis, h)) {
+ if (GetDefiniteSize(styleMaxBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) ||
+ (aPercentageBasis.isNothing() &&
+ GetPercentBSize(styleMaxBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord maxISize = NSCoordMulDiv(h, ratioISize, ratioBSize);
if (maxISize < result) {
@@ -5130,8 +5242,9 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
}
}
- if (GetAbsoluteCoord(styleMinBSize, h) ||
- GetPercentBSize(styleMinBSize, aFrame, horizontalAxis, h)) {
+ if (GetDefiniteSize(styleMinBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) ||
+ (aPercentageBasis.isNothing() &&
+ GetPercentBSize(styleMinBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord minISize = NSCoordMulDiv(h, ratioISize, ratioBSize);
if (minISize > result) {
@@ -5158,8 +5271,8 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
}
nsIFrame::IntrinsicISizeOffsetData offsets =
- MOZ_LIKELY(aAxis == ourInlineAxis) ? aFrame->IntrinsicISizeOffsets()
- : aFrame->IntrinsicBSizeOffsets();
+ MOZ_LIKELY(isInlineAxis) ? aFrame->IntrinsicISizeOffsets()
+ : aFrame->IntrinsicBSizeOffsets();
nscoord contentBoxSize = result;
result = AddIntrinsicSizeOffset(aRenderingContext, aFrame, offsets, aType,
boxSizing, result, min, styleISize,
@@ -5196,7 +5309,7 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext* aRenderingContext,
// We want the size aFrame will contribute to its parent's inline-size.
PhysicalAxis axis =
aFrame->GetParent()->GetWritingMode().PhysicalAxis(eLogicalAxisInline);
- return IntrinsicForAxis(axis, aRenderingContext, aFrame, aType, aFlags);
+ return IntrinsicForAxis(axis, aRenderingContext, aFrame, aType, Nothing(), aFlags);
}
/* static */ nscoord
@@ -7242,9 +7355,11 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement,
(aSurfaceFlags & SFE_PREFER_NO_PREMULTIPLY_ALPHA) == 0,
"We can't support non-premultiplied alpha for video!");
+#ifdef MOZ_EME
if (aElement->ContainsRestrictedContent()) {
return result;
}
+#endif
uint16_t readyState;
if (NS_SUCCEEDED(aElement->GetReadyState(&readyState)) &&
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
index d9580a3df..97fc410b0 100644
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1378,6 +1378,10 @@ public:
* width, its 'width', 'min-width', and 'max-width' properties (or 'height'
* variations if that's what matches aAxis) and its padding, border and margin
* in the corresponding dimension.
+ * @param aPercentageBasis an optional percentage basis (in aFrame's WM).
+ * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes.
+ * If you pass Nothing() a percentage basis will be calculated from aFrame's
+ * ancestors' computed size in the relevant axis, if needed.
* @param aMarginBoxMinSizeClamp make the result fit within this margin-box
* size by reducing the *content size* (flooring at zero). This is used for:
* https://drafts.csswg.org/css-grid/#min-size-auto
@@ -1396,6 +1400,7 @@ public:
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
+ const mozilla::Maybe<mozilla::LogicalSize>& aPercentageBasis = mozilla::Nothing(),
uint32_t aFlags = 0,
nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
/**
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
index b27e6d0e3..4a54a8432 100644
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -208,6 +208,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
mTextZoom(1.0), mFullZoom(1.0), mOverrideDPPX(0.0),
mLastFontInflationScreenSize(gfxSize(-1.0, -1.0)),
mPageSize(-1, -1), mPPScale(1.0f),
+ mViewportScrollbarOverrideNode(nullptr),
mViewportStyleScrollbar(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
mImageAnimationModePref(imgIContainer::kNormalAnimMode),
mAllInvalidated(false),
@@ -1423,10 +1424,10 @@ nsPresContext::UpdateViewportScrollbarStylesOverride()
// Start off with our default styles, and then update them as needed.
mViewportStyleScrollbar = ScrollbarStyles(NS_STYLE_OVERFLOW_AUTO,
NS_STYLE_OVERFLOW_AUTO);
- nsIContent* propagatedFrom = nullptr;
+ mViewportScrollbarOverrideNode = nullptr;
// Don't propagate the scrollbar state in printing or print preview.
if (!IsPaginated()) {
- propagatedFrom =
+ mViewportScrollbarOverrideNode =
GetPropagatedScrollbarStylesForViewport(this, &mViewportStyleScrollbar);
}
@@ -1438,13 +1439,13 @@ nsPresContext::UpdateViewportScrollbarStylesOverride()
// the styles are from, so that the state of those elements is not
// affected across fullscreen change.
if (fullscreenElement != document->GetRootElement() &&
- fullscreenElement != propagatedFrom) {
+ fullscreenElement != mViewportScrollbarOverrideNode) {
mViewportStyleScrollbar = ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN,
NS_STYLE_OVERFLOW_HIDDEN);
}
}
- return propagatedFrom;
+ return mViewportScrollbarOverrideNode;
}
bool
@@ -1696,6 +1697,9 @@ nsPresContext::SysColorChangedInternal()
sLookAndFeelChanged = false;
}
+ // Invalidate cached '-moz-windows-accent-color-applies' media query:
+ nsCSSRuleProcessor::FreeSystemMetrics();
+
// Reset default background and foreground colors for the document since
// they may be using system colors
GetDocumentColorPreferences();
diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h
index 4fdc60a2e..d8f876291 100644
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -719,7 +719,18 @@ public:
* it was propagated from.
*/
nsIContent* UpdateViewportScrollbarStylesOverride();
- const ScrollbarStyles& GetViewportScrollbarStylesOverride()
+
+ /**
+ * Returns the cached result from the last call to
+ * UpdateViewportScrollbarStylesOverride() -- i.e. return the node
+ * whose scrollbar styles we have propagated to the viewport (or nullptr if
+ * there is no such node).
+ */
+ nsIContent* GetViewportScrollbarStylesOverrideNode() const {
+ return mViewportScrollbarOverrideNode;
+ }
+
+ const ScrollbarStyles& GetViewportScrollbarStylesOverride() const
{
return mViewportStyleScrollbar;
}
@@ -1310,7 +1321,16 @@ protected:
nscolor mBodyTextColor;
+ // This is a non-owning pointer. May be null. If non-null, it's guaranteed
+ // to be pointing to a node that's still alive, because we'll reset it in
+ // UpdateViewportScrollbarStylesOverride() as part of the cleanup code
+ // when this node is removed from the document. (For <body> and the root node,
+ // this call happens in nsCSSFrameConstructor::ContentRemoved(). For
+ // fullscreen elements, it happens in the fullscreen-specific cleanup
+ // invoked by Element::UnbindFromTree().)
+ nsIContent* MOZ_NON_OWNING_REF mViewportScrollbarOverrideNode;
ScrollbarStyles mViewportStyleScrollbar;
+
uint8_t mFocusRingWidth;
bool mExistThrottledUpdates;
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index 56ac370b9..42b39c860 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6514,10 +6514,11 @@ nsIPresShell::GetPointerCapturingContent(uint32_t aPointerId)
}
/* static */ void
-nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId,
- uint16_t aPointerType, bool aIsPrimary)
+nsIPresShell::CheckPointerCaptureState(const WidgetPointerEvent* aPointerEvent)
{
- PointerCaptureInfo* captureInfo = GetPointerCaptureInfo(aPointerId);
+ PointerCaptureInfo* captureInfo =
+ GetPointerCaptureInfo(aPointerEvent->pointerId);
+
if (captureInfo &&
captureInfo->mPendingContent != captureInfo->mOverrideContent) {
// cache captureInfo->mPendingContent since it may be changed in the pointer
@@ -6525,17 +6526,16 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId,
nsIContent* pendingContent = captureInfo->mPendingContent.get();
if (captureInfo->mOverrideContent) {
DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false,
- aPointerId, aPointerType, aIsPrimary,
+ aPointerEvent,
captureInfo->mOverrideContent);
}
if (pendingContent) {
- DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aPointerId,
- aPointerType, aIsPrimary,
- pendingContent);
+ DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true,
+ aPointerEvent, pendingContent);
}
captureInfo->mOverrideContent = pendingContent;
if (captureInfo->Empty()) {
- sPointerCaptureList->Remove(aPointerId);
+ sPointerCaptureList->Remove(aPointerEvent->pointerId);
}
}
}
@@ -6976,37 +6976,30 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
return NS_OK;
}
-class ReleasePointerCaptureCaller
+class ReleasePointerCaptureCaller final
{
public:
- ReleasePointerCaptureCaller() :
- mPointerId(0),
- mPointerType(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN),
- mIsPrimary(false),
- mIsSet(false)
+ ReleasePointerCaptureCaller()
+ : mPointerEvent(nullptr)
{
}
~ReleasePointerCaptureCaller()
{
- if (mIsSet) {
- nsIPresShell::ReleasePointerCapturingContent(mPointerId);
- nsIPresShell::CheckPointerCaptureState(mPointerId, mPointerType,
- mIsPrimary);
+ if (mPointerEvent) {
+ nsIPresShell::ReleasePointerCapturingContent(mPointerEvent->pointerId);
+ nsIPresShell::CheckPointerCaptureState(mPointerEvent);
}
}
- void SetTarget(uint32_t aPointerId, uint16_t aPointerType, bool aIsPrimary)
+
+ void SetTarget(const WidgetPointerEvent* aPointerEvent)
{
- mPointerId = aPointerId;
- mPointerType = aPointerType;
- mIsPrimary = aIsPrimary;
- mIsSet = true;
+ MOZ_ASSERT(aPointerEvent);
+ mPointerEvent = aPointerEvent;
}
private:
- int32_t mPointerId;
- uint16_t mPointerType;
- bool mIsPrimary;
- bool mIsSet;
+ // This is synchronously used inside PresShell::HandleEvent.
+ const WidgetPointerEvent* mPointerEvent;
};
static bool
@@ -7719,9 +7712,7 @@ PresShell::HandleEvent(nsIFrame* aFrame,
nsWeakFrame frameKeeper(frame);
// Handle pending pointer capture before any pointer events except
// gotpointercapture / lostpointercapture.
- CheckPointerCaptureState(pointerEvent->pointerId,
- pointerEvent->inputSource,
- pointerEvent->mIsPrimary);
+ CheckPointerCaptureState(pointerEvent);
// Prevent application crashes, in case damaged frame.
if (!frameKeeper.IsAlive()) {
frame = nullptr;
@@ -7742,33 +7733,29 @@ PresShell::HandleEvent(nsIFrame* aFrame,
}
}
- if (aEvent->mClass == ePointerEventClass &&
- aEvent->mMessage != ePointerDown) {
- if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
- uint32_t pointerId = pointerEvent->pointerId;
+ // Mouse events should be fired to the same target as their mapped pointer
+ // events
+ if ((aEvent->mClass == ePointerEventClass ||
+ aEvent->mClass == eMouseEventClass) &&
+ aEvent->mMessage != ePointerDown && aEvent->mMessage != eMouseDown) {
+ if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
+ uint32_t pointerId = mouseEvent->pointerId;
nsIContent* pointerCapturingContent =
GetPointerCapturingContent(pointerId);
if (pointerCapturingContent) {
if (nsIFrame* capturingFrame = pointerCapturingContent->GetPrimaryFrame()) {
- // If pointer capture is set, we should suppress
- // pointerover/pointerenter events for all elements except element
- // which have pointer capture. (Code in EventStateManager)
- pointerEvent->retargetedByPointerCapture =
- frame && frame->GetContent() &&
- !nsContentUtils::ContentIsDescendantOf(frame->GetContent(),
- pointerCapturingContent);
frame = capturingFrame;
}
- if (pointerEvent->mMessage == ePointerUp ||
- pointerEvent->mMessage == ePointerCancel) {
+ if (aEvent->mMessage == ePointerUp ||
+ aEvent->mMessage == ePointerCancel) {
// Implicitly releasing capture for given pointer.
// ePointerLostCapture should be send after ePointerUp or
// ePointerCancel.
- releasePointerCaptureCaller.SetTarget(pointerId,
- pointerEvent->inputSource,
- pointerEvent->mIsPrimary);
+ WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent();
+ MOZ_ASSERT(pointerEvent);
+ releasePointerCaptureCaller.SetTarget(pointerEvent);
}
}
}
@@ -8204,6 +8191,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
}
case eMouseDown:
case eMouseUp:
+ case ePointerDown:
+ case ePointerUp:
isHandlingUserInput = true;
break;
@@ -8340,35 +8329,44 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
return rv;
}
-void
-nsIPresShell::DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture,
- uint32_t aPointerId,
- uint16_t aPointerType,
- bool aIsPrimary,
- nsIContent* aCaptureTarget)
-{
- PointerEventInit init;
- init.mPointerId = aPointerId;
- init.mBubbles = true;
- ConvertPointerTypeToString(aPointerType, init.mPointerType);
- init.mIsPrimary = aIsPrimary;
- RefPtr<mozilla::dom::PointerEvent> event;
- event = PointerEvent::Constructor(aCaptureTarget,
- aIsGotCapture
- ? NS_LITERAL_STRING("gotpointercapture")
- : NS_LITERAL_STRING("lostpointercapture"),
- init);
- if (event) {
+/* static */ void
+nsIPresShell::DispatchGotOrLostPointerCaptureEvent(
+ bool aIsGotCapture,
+ const WidgetPointerEvent* aPointerEvent,
+ nsIContent* aCaptureTarget)
+{
+ nsIDocument* targetDoc = aCaptureTarget->OwnerDoc();
+ nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
+ NS_ENSURE_TRUE_VOID(shell);
+
+ if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
+ // If the capturing element was removed from the DOM tree, fire
+ // ePointerLostCapture at the document.
+ PointerEventInit init;
+ init.mPointerId = aPointerEvent->pointerId;
+ init.mBubbles = true;
+ init.mComposed = true;
+ ConvertPointerTypeToString(aPointerEvent->inputSource, init.mPointerType);
+ init.mIsPrimary = aPointerEvent->mIsPrimary;
+ RefPtr<mozilla::dom::PointerEvent> event;
+ event = PointerEvent::Constructor(aCaptureTarget,
+ NS_LITERAL_STRING("lostpointercapture"),
+ init);
bool dummy;
- // If the capturing element was removed from the DOM tree,
- // lostpointercapture event should be fired at the document.
- if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
- aCaptureTarget->OwnerDoc()->DispatchEvent(event->InternalDOMEvent(),
- &dummy);
- } else {
- aCaptureTarget->DispatchEvent(event->InternalDOMEvent(), &dummy);
- }
+ targetDoc->DispatchEvent(event->InternalDOMEvent(), &dummy);
+ return;
}
+ nsEventStatus status = nsEventStatus_eIgnore;
+ WidgetPointerEvent localEvent(aPointerEvent->IsTrusted(),
+ aIsGotCapture ? ePointerGotCapture :
+ ePointerLostCapture,
+ aPointerEvent->mWidget);
+ localEvent.AssignPointerEventData(*aPointerEvent, true);
+ nsresult rv = shell->HandleEventWithTarget(
+ &localEvent,
+ aCaptureTarget->GetPrimaryFrame(),
+ aCaptureTarget, &status);
+ NS_ENSURE_SUCCESS_VOID(rv);
}
nsresult
diff --git a/layout/base/tests/bug1078327_inner.html b/layout/base/tests/bug1078327_inner.html
index 9e32fc996..0cfb9da7f 100644
--- a/layout/base/tests/bug1078327_inner.html
+++ b/layout/base/tests/bug1078327_inner.html
@@ -24,16 +24,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
var test_mediator_move = false;
var test_mediator_out = false;
var test_listener = false;
+ var test_lost_capture = false;
function TargetHandler(event) {
logger("Target receive event: " + event.type + ". Mediator.setPointerCapture()");
mediator.setPointerCapture(event.pointerId);
test_target = true;
+ test_capture = true;
}
function MediatorHandler(event) {
logger("Mediator receive event: " + event.type);
- if(event.type == "gotpointercapture")
- test_capture = true;
if(!test_capture)
return;
if(event.type == "pointermove")
@@ -43,7 +43,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
if(event.type == "pointerout")
test_mediator_out++;
if(event.type == "lostpointercapture")
- test_capture = false;
+ test_lost_capture = true;
}
function ListenerHandler(event) {
logger("Listener receive event: " + event.type);
@@ -86,7 +86,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
}
function finishTest() {
parent.is(test_target, true, "pointerdown event should be received by target");
- parent.is(test_capture, false, "test_capture should be false at the end of the test");
+ parent.is(test_lost_capture, true, "mediator should receive lostpointercapture");
parent.is(test_mediator_over, 1, "mediator should receive pointerover event only once");
parent.is(test_mediator_move, 5, "mediator should receive pointermove event five times");
parent.is(test_mediator_out, 1, "mediator should receive pointerout event only once");
diff --git a/layout/base/tests/bug1162990_inner_1.html b/layout/base/tests/bug1162990_inner_1.html
index 4ea5edb5c..0f950df8d 100644
--- a/layout/base/tests/bug1162990_inner_1.html
+++ b/layout/base/tests/bug1162990_inner_1.html
@@ -111,10 +111,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
}
function finishTest() {
- parent.is(test_basketLeave, 0, "Part1: basket should not receive pointerleave event after pointer capturing");
+ parent.is(test_basketLeave, 1, "Part1: basket should receive pointerleave event after pointer capturing");
parent.is(test_targetGotCapture, 1, "Part1: target should receive gotpointercapture event");
parent.is(test_targetLostCapture, 1, "Part1: target should receive lostpointercapture event");
- parent.is(test_targetLeave, 2, "Part1: target should receive pointerleave event two times");
+ parent.is(test_targetLeave, 1, "Part1: target should receive pointerleave event only one time");
parent.is(test_childLeave, 0, "Part1: child should not receive pointerleave event after pointer capturing");
parent.is(test_listenerDown, 1, "Part1: listener should receive pointerdown event");
parent.is(test_listenerLeave, 1, "Part1: listener should receive pointerleave event only one time");
diff --git a/layout/base/tests/bug1162990_inner_2.html b/layout/base/tests/bug1162990_inner_2.html
index 54aa74ca3..e418927bd 100644
--- a/layout/base/tests/bug1162990_inner_2.html
+++ b/layout/base/tests/bug1162990_inner_2.html
@@ -116,7 +116,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
parent.is(test_targetDown, 1, "Part2: target should receive pointerdown event");
parent.is(test_targetGotCapture, 1, "Part2: target should receive gotpointercapture event");
parent.is(test_targetLostCapture, 1, "Part2: target should receive lostpointercapture event");
- parent.is(test_targetLeave, 1, "Part2: target should receive pointerleave event");
+ parent.is(test_targetLeave, 0, "Part2: target should not receive pointerleave event");
parent.is(test_childLeave, 0, "Part2: child should not receive pointerleave event after pointer capturing");
parent.is(test_listenerLeave, 0, "Part2: listener should not receive pointerleave event after pointer capturing");
logger("finishTest");
diff --git a/layout/base/tests/bug976963_inner.html b/layout/base/tests/bug976963_inner.html
deleted file mode 100644
index 2c55fbccd..000000000
--- a/layout/base/tests/bug976963_inner.html
+++ /dev/null
@@ -1,241 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=976963
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 976963</title>
- <meta name="author" content="Maksim Lebedev" />
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <style>
- div#listener {
- background: yellow;
- position: absolute;
- top: -100px;
- }
- div#middler {
- background: yellow;
- margin: 10px;
- }
- div#target {
- background: yellow;
- }
- </style>
- <script type="application/javascript">
- /** Test for Bug 976963 **/
- var All_Pointer_Events = ["pointerover", "pointerenter",
- "pointermove",
- "pointerdown", "pointerup",
- "pointerout", "pointerleave",
- "pointercancel",
- "gotpointercapture", "lostpointercapture"];
-
- function on_event(object, event, callback) {
- object.addEventListener(event, callback, false);
- }
- function ok(check, msg) {
- parent.ok(check, msg);
- }
- function is(a, b, msg) {
- parent.is(a, b, msg);
- }
-
- var listener = undefined;
- var middler = undefined;
- var target = undefined;
-
- var test_ListenerGotCapture = 0;
- var test_ListenerUnwanted = 0;
- var test_ListenerLostCapture = 0;
- var test_ListenerAfterCapture = 0;
- var test_MiddlerGotCapture = 0;
- var test_MiddlerOver = 0;
- var test_MiddlerLeave = 0;
- var test_MiddlerUp = 0;
- var test_MiddlerLostCapture = 0;
- var test_TargetDown = 0;
- var test_TargetUnwanted = 0;
- var test_TargetUp = 0;
-
- var captured_event = undefined;
- var f_gotPointerCapture = false;
- var f_lostPointerCapture = false;
- var f_gotMiddlerPointerCapture = false;
-
- function listenerEventHandler(event) {
- logger("Listener: " + event.type + ". Captured_event: " + captured_event);
- if(test_ListenerLostCapture)
- test_ListenerAfterCapture++;
- if (event.type == "gotpointercapture") {
- f_gotPointerCapture = true;
- test_ListenerGotCapture++;
- }
- else if (event.type == "lostpointercapture") {
- f_lostPointerCapture = true;
- f_gotPointerCapture = false;
- test_ListenerLostCapture++;
- }
- else if (event.type == "pointermove") {
- ok(captured_event && captured_event.pointerId == event.pointerId, "Listener: equals pointerId for lostpointercapture event");
- if (f_gotPointerCapture) {
- // on first event received for capture, release capture
- logger("Listener call release");
- ok(!!listener, "Listener should be live!");
- ok(typeof(listener.releasePointerCapture) == "function", "Listener should have a function releasePointerCapture");
- listener.releasePointerCapture(event.pointerId);
- }
- else {
- logger("Listener.ASSERT: " + event.type);
- test_ListenerUnwanted++;
- // if any other events are received after releaseCapture, then the test fails
- ok(false, event.target.id + "-" + event.type + " should be handled by target element handler");
- }
- }
- else {
- test_ListenerUnwanted++;
- logger("Listener.ASSERT: " + event.type);
- ok(false, event.type + "should be never handled by listener");
- }
- }
-
- function middlerEventHandler(event) {
- logger("Middler: " + event.type + ". Captured_event: " + captured_event);
- if (event.type == "gotpointercapture") {
- test_MiddlerGotCapture++;
- f_gotMiddlerPointerCapture = true;
- ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for gotpointercapture event");
- }
- else if (event.type == "pointerover") {
- test_MiddlerOver++;
- ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for pointerover event");
- }
- else if (event.type == "pointerleave") {
- test_MiddlerLeave++;
- ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for pointerleave event");
- ok(!!listener, "Listener should be live!");
- ok(typeof(listener.setPointerCapture) == "function", "Listener should have a function setPointerCapture");
- listener.setPointerCapture(event.pointerId);
- }
- else if (event.type == "lostpointercapture") {
- test_MiddlerLostCapture++;
- f_gotMiddlerPointerCapture = false;
- ok(captured_event && captured_event.pointerId == event.pointerId, "Middler: equals pointerId for lostpointercapture event");
- }
- else if (event.type == "pointerup" ) {
- test_MiddlerUp++;
- }
- }
-
- function targetEventHandler(event) {
- logger("Target: " + event.type + ". Captured_event: " + captured_event);
- if (f_gotPointerCapture || f_gotMiddlerPointerCapture) {
- if (event.type != "pointerout" && event.type != "pointerleave") {
- logger("Target.ASSERT: " + event.type + " " + event.pointerId);
- test_TargetUnwanted++;
- ok(false, "The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
- }
- }
- if (event.type == "pointerdown") {
- logger("Target.pointerdown 1: " + captured_event);
- test_TargetDown++;
- captured_event = event;
- ok(!!middler, "Middler should be live!");
- ok(typeof(middler.setPointerCapture) == "function", "Middler should have a function setPointerCapture");
- middler.setPointerCapture(event.pointerId);
- logger("Target.pointerdown 2: " + captured_event);
- }
- else if (event.type == "pointerup") {
- ok(f_lostPointerCapture, "Target should have received pointerup");
- ok(captured_event && captured_event.pointerId == event.pointerId, "Target: equals pointerId for lostpointercapture event");
- test_TargetUp++; // complete test
- }
- }
-
- function colorerHandler(event) {
- if(event.type == "pointerover")
- event.target.style.background = "red";
- else if(event.type == "pointerout")
- event.target.style.background = "yellow";
- }
-
- function setEventHandlers() {
- listener = document.getElementById("listener");
- middler = document.getElementById("middler");
- target = document.getElementById("target");
- target.style["touchAction"] = "none";
-
- // target and listener - handle all events
- for (var i = 0; i < All_Pointer_Events.length; i++) {
- on_event(target, All_Pointer_Events[i], targetEventHandler);
- on_event(listener, All_Pointer_Events[i], listenerEventHandler);
- on_event(middler, All_Pointer_Events[i], middlerEventHandler);
- on_event(target, All_Pointer_Events[i], colorerHandler);
- on_event(middler, All_Pointer_Events[i], colorerHandler);
- }
- }
-
- function prepareTest() {
- SpecialPowers.pushPrefEnv({
- "set": [
- ["dom.w3c_pointer_events.enabled", true]
- ]
- }, executeTest);
- }
-
- function executeTest()
- {
- logger("executeTest");
- setEventHandlers();
- document.body.offsetLeft;
- var rect = target.getBoundingClientRect();
- synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
- synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
- synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
- synthesizePointer(middler, rect.width/2, rect.height/2, {type: "pointermove"});
- synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
- synthesizePointer(middler, rect.width/2, rect.height/2, {type: "pointermove"});
- synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
- synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
- finishTest();
- }
-
- function finishTest() {
- setTimeout(function() {
- is(test_ListenerGotCapture, 1, "Listener should receive gotpointercapture event");
- is(test_ListenerUnwanted, 0, "Listener should not receive any unwanted events");
- is(test_ListenerLostCapture, 1, "Listener should receive lostpointercapture event");
- is(test_ListenerAfterCapture, 0, "Listener should not receive any events after release pointer capture");
- is(test_MiddlerGotCapture, 1, "Middler should receive gotpointercapture event");
- is(test_MiddlerOver, 1, "Middler should receive pointerover event");
- is(test_MiddlerLeave, 1, "Middler should receive pointerleave event");
- is(test_MiddlerUp, 0, "Middler should not receive pointerup event");
- is(test_MiddlerLostCapture, 1, "Middler should receive lostpointercapture event");
- is(test_TargetDown, 1, "Target should receive pointerdown event");
- is(test_TargetUnwanted, 0, "Target should not receive any event while pointer capture is active");
- is(test_TargetUp, 1, "Target should receive pointerup event");
- logger("finishTest");
- parent.finishTest();
- }, 1000);
- }
-
- function logger(message) {
- console.log(message);
- var log = document.getElementById('log');
- log.innerHTML = message + "<br>" + log.innerHTML;
- }
- </script>
-</head>
-<body onload="prepareTest()">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=976963">Mozilla Bug 976963</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
- <div id="listener">div id=listener</div>
- <div id="middler">div id=middler</div>
- <div id="target">div id=target</div>
- <pre id="log">
- </pre>
-</body>
-</html>
diff --git a/layout/base/tests/bug977003_inner_5.html b/layout/base/tests/bug977003_inner_5.html
index 70fc5ba40..81094043c 100644
--- a/layout/base/tests/bug977003_inner_5.html
+++ b/layout/base/tests/bug977003_inner_5.html
@@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
var test_lost_listener = false;
var test_lost_type = "";
var test_move_listener = false;
+ var test_over_listener = false;
var test_listener = false;
var test_lost_primary = false;
@@ -53,6 +54,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
logger("Receive event on Listener: " + event.type);
test_move_listener = true;
}
+ function ListenerOverHandler(event) {
+ logger("Receive event on Listener: " + event.type);
+ test_over_listener = true;
+ }
function ListenerHandler(event) {
logger("Receive event on Listener: " + event.type);
test_listener = true;
@@ -74,7 +79,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
target.addEventListener("pointerdown", TargetDownHandler, false);
listener.addEventListener("gotpointercapture", ListenerGotPCHandler, false);
listener.addEventListener("lostpointercapture", ListenerLostPCHandler, false);
- listener.addEventListener("pointerover", ListenerHandler, false);
+ listener.addEventListener("pointerover", ListenerOverHandler, false);
listener.addEventListener("pointermove", ListenerMoveHandler, false);
listener.addEventListener("pointerup", ListenerHandler, false);
listener.addEventListener("pointerout", ListenerHandler, false);
@@ -93,6 +98,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
parent.is(test_lost_type, "touch", "Part 5: lostpointercapture event should have pointerType touch");
parent.is(test_lost_primary, true, "Part 5: lostpointercapture event should have isPrimary as true");
parent.is(test_move_listener, true, "Part 5: gotpointercapture should be triggered by pointermove");
+ parent.is(test_over_listener, true, "Part 5: listener should receive pointerover when capturing pointer");
parent.is(test_listener, false, "Part 5: listener should not receive any other events");
logger("finishTest");
parent.finishTest();
diff --git a/layout/base/tests/bug977003_inner_6.html b/layout/base/tests/bug977003_inner_6.html
index 12424b1f2..b60ca5c31 100644
--- a/layout/base/tests/bug977003_inner_6.html
+++ b/layout/base/tests/bug977003_inner_6.html
@@ -19,6 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
var listener = undefined;
var test_target = false;
var test_move = false;
+ var test_over = false;
var test_listener = false;
var receive_lostpointercapture = false;
@@ -44,6 +45,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
}
} else if(event.type == "pointermove") {
test_move = true;
+ } else if(event.type == "pointerover") {
+ test_over = true;
} else {
test_listener = true;
}
@@ -81,7 +84,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
// PE level 2 defines that the pending pointer capture is processed when firing next pointer events.
// In this test case, pointer capture release is processed when firing pointermove
parent.is(test_move, true, "Part 6: gotpointercapture should be triggered by pointermove");
- parent.is(test_listener, false, "Part 6: no other pointerevents should be fired before gotpointercapture");
+ parent.is(test_over, true, "Part 6: pointerover should be received when capturing pointer");
+ parent.is(test_listener, false, "Part 6: no other pointerevents should be fired before gotpointercapture except pointerover");
logger("finishTest");
parent.finishTest();
}
diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini
index 279b0af8a..405697977 100644
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -256,8 +256,6 @@ skip-if = toolkit == 'android'
support-files = bug851445_helper.html
[test_bug970964.html]
support-files = bug970964_inner.html
-[test_bug976963.html]
-support-files = bug976963_inner.html
[test_bug977003.html]
support-files =
bug977003_inner_1.html
diff --git a/layout/base/tests/test_bug976963.html b/layout/base/tests/test_bug976963.html
deleted file mode 100644
index 4b8da3a6e..000000000
--- a/layout/base/tests/test_bug976963.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=976963
--->
- <head>
- <meta charset="utf-8">
- <meta name="author" content="Maksim Lebedev" />
- <title>Test for Bug 976963</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript">
- function prepareTest() {
- SimpleTest.waitForExplicitFinish();
- SimpleTest.requestFlakyTimeout("untriaged");
- SpecialPowers.pushPrefEnv({
- "set": [
- ["dom.w3c_pointer_events.enabled", true],
- ["layout.reflow.synthMouseMove", false]
- ]
- }, startTest);
- }
- function startTest() {
- var iframe = document.getElementById("testFrame");
- iframe.src = "bug976963_inner.html";
- }
- function finishTest() {
- SimpleTest.finish();
- }
- </script>
- </head>
- <body onload="prepareTest()">
- <iframe id="testFrame" height="700" width="700"></iframe>
- </body>
-</html>
diff --git a/layout/forms/nsDateTimeControlFrame.cpp b/layout/forms/nsDateTimeControlFrame.cpp
index df2e43986..fa22dceba 100644
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -372,7 +372,8 @@ nsDateTimeControlFrame::AttributeChanged(int32_t aNameSpaceID,
auto contentAsInputElem = static_cast<dom::HTMLInputElement*>(mContent);
// If script changed the <input>'s type before setting these attributes
// then we don't need to do anything since we are going to be reframed.
- if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME) {
+ if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME ||
+ contentAsInputElem->GetType() == NS_FORM_INPUT_DATE) {
if (aAttribute == nsGkAtoms::value) {
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp
index befd41ee2..fc9f0571b 100644
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -5,26 +5,22 @@
#include "nsFieldSetFrame.h"
+#include <algorithm>
#include "mozilla/gfx/2D.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Maybe.h"
#include "nsCSSAnonBoxes.h"
-#include "nsLayoutUtils.h"
-#include "nsLegendFrame.h"
#include "nsCSSRendering.h"
-#include <algorithm>
-#include "nsIFrame.h"
-#include "nsPresContext.h"
-#include "mozilla/RestyleManager.h"
-#include "nsGkAtoms.h"
-#include "nsStyleConsts.h"
#include "nsDisplayList.h"
+#include "nsGkAtoms.h"
+#include "nsIFrameInlines.h"
+#include "nsLayoutUtils.h"
+#include "nsLegendFrame.h"
#include "nsRenderingContext.h"
-#include "nsIScrollableFrame.h"
-#include "mozilla/Likely.h"
-#include "mozilla/Maybe.h"
+#include "nsStyleConsts.h"
using namespace mozilla;
using namespace mozilla::gfx;
-using namespace mozilla::image;
using namespace mozilla::layout;
nsContainerFrame*
@@ -126,7 +122,7 @@ void
nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
- DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
+ image::DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
PaintBorder(aBuilder, *aCtx, ToReferenceFrame(), mVisibleRect);
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
@@ -210,7 +206,7 @@ nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
contentDisplayItems.MoveTo(aLists);
}
-DrawResult
+image::DrawResult
nsFieldSetFrame::PaintBorder(
nsDisplayListBuilder* aBuilder,
nsRenderingContext& aRenderingContext,
@@ -695,9 +691,50 @@ nsFieldSetFrame::AccessibleType()
#endif
nscoord
-nsFieldSetFrame::GetLogicalBaseline(WritingMode aWritingMode) const
+nsFieldSetFrame::GetLogicalBaseline(WritingMode aWM) const
+{
+ switch (StyleDisplay()->mDisplay) {
+ case mozilla::StyleDisplay::Grid:
+ case mozilla::StyleDisplay::InlineGrid:
+ case mozilla::StyleDisplay::Flex:
+ case mozilla::StyleDisplay::InlineFlex:
+ return BaselineBOffset(aWM, BaselineSharingGroup::eFirst,
+ AlignmentContext::eInline);
+ default:
+ return BSize(aWM) - BaselineBOffset(aWM, BaselineSharingGroup::eLast,
+ AlignmentContext::eInline);
+ }
+}
+
+bool
+nsFieldSetFrame::GetVerticalAlignBaseline(WritingMode aWM,
+ nscoord* aBaseline) const
{
nsIFrame* inner = GetInner();
- return inner->BStart(aWritingMode, GetParent()->GetSize()) +
- inner->GetLogicalBaseline(aWritingMode);
+ MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM));
+ if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) {
+ return false;
+ }
+ nscoord innerBStart = inner->BStart(aWM, GetSize());
+ *aBaseline += innerBStart;
+ return true;
+}
+
+bool
+nsFieldSetFrame::GetNaturalBaselineBOffset(WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const
+{
+ nsIFrame* inner = GetInner();
+ MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM));
+ if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) {
+ return false;
+ }
+ nscoord innerBStart = inner->BStart(aWM, GetSize());
+ if (aBaselineGroup == BaselineSharingGroup::eFirst) {
+ *aBaseline += innerBStart;
+ } else {
+ *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM));
+ }
+ return true;
}
diff --git a/layout/forms/nsFieldSetFrame.h b/layout/forms/nsFieldSetFrame.h
index 54eaf678f..5eb67c320 100644
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -7,7 +7,7 @@
#define nsFieldSetFrame_h___
#include "mozilla/Attributes.h"
-#include "imgIContainer.h"
+#include "DrawResult.h"
#include "nsContainerFrame.h"
class nsFieldSetFrame final : public nsContainerFrame
@@ -33,7 +33,6 @@ public:
const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding,
ComputeSizeFlags aFlags) override;
- virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
/**
* The area to paint box-shadows around. It's the border rect except
@@ -46,6 +45,13 @@ public:
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
+ nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override;
+ bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
+ nscoord* aBaseline) const override;
+ bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const override;
+
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp
index ef9459ef2..2e4fa9f67 100644
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -418,6 +418,47 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
aButtonDesiredSize.SetOverflowAreasToDesiredBounds();
}
+bool
+nsHTMLButtonControlFrame::GetVerticalAlignBaseline(mozilla::WritingMode aWM,
+ nscoord* aBaseline) const
+{
+ nsIFrame* inner = mFrames.FirstChild();
+ if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) {
+ return false;
+ }
+ if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) {
+ // <input type=color> has an empty block frame as inner frame
+ *aBaseline = inner->
+ SynthesizeBaselineBOffsetFromBorderBox(aWM, BaselineSharingGroup::eFirst);
+ }
+ nscoord innerBStart = inner->BStart(aWM, GetSize());
+ *aBaseline += innerBStart;
+ return true;
+}
+
+bool
+nsHTMLButtonControlFrame::GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const
+{
+ nsIFrame* inner = mFrames.FirstChild();
+ if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) {
+ return false;
+ }
+ if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) {
+ // <input type=color> has an empty block frame as inner frame
+ *aBaseline = inner->
+ SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup);
+ }
+ nscoord innerBStart = inner->BStart(aWM, GetSize());
+ if (aBaselineGroup == BaselineSharingGroup::eFirst) {
+ *aBaseline += innerBStart;
+ } else {
+ *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM));
+ }
+ return true;
+}
+
nsresult nsHTMLButtonControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
{
if (nsGkAtoms::value == aName) {
diff --git a/layout/forms/nsHTMLButtonControlFrame.h b/layout/forms/nsHTMLButtonControlFrame.h
index 96ad0f366..432afa12c 100644
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -39,6 +39,13 @@ public:
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
+ bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
+ nscoord* aBaseline) const override;
+
+ bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const override;
+
virtual nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
diff --git a/layout/forms/nsLegendFrame.h b/layout/forms/nsLegendFrame.h
index 5f5e1e03e..a9e11cbbe 100644
--- a/layout/forms/nsLegendFrame.h
+++ b/layout/forms/nsLegendFrame.h
@@ -9,7 +9,8 @@
#include "mozilla/Attributes.h"
#include "nsBlockFrame.h"
-class nsLegendFrame : public nsBlockFrame {
+class nsLegendFrame final : public nsBlockFrame
+{
public:
NS_DECL_QUERYFRAME_TARGET(nsLegendFrame)
NS_DECL_QUERYFRAME
@@ -30,7 +31,7 @@ public:
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
- int32_t GetLogicalAlign(WritingMode aCBWM);
+ int32_t GetLogicalAlign(mozilla::WritingMode aCBWM);
};
diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp
index f85bc2a80..a7f7d40a8 100644
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -106,6 +106,7 @@ private:
nsTextControlFrame::nsTextControlFrame(nsStyleContext* aContext)
: nsContainerFrame(aContext)
+ , mFirstBaseline(NS_INTRINSIC_WIDTH_UNKNOWN)
, mEditorHasBeenInitialized(false)
, mIsProcessing(false)
#ifdef DEBUG
@@ -538,20 +539,20 @@ nsTextControlFrame::Reflow(nsPresContext* aPresContext,
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
aDesiredSize.SetSize(wm, finalSize);
- // computation of the ascent wrt the input height
+ // Calculate the baseline and store it in mFirstBaseline.
nscoord lineHeight = aReflowInput.ComputedBSize();
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
if (!IsSingleLineTextControl()) {
lineHeight = ReflowInput::CalcLineHeight(GetContent(), StyleContext(),
- NS_AUTOHEIGHT, inflation);
+ NS_AUTOHEIGHT, inflation);
}
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
- // now adjust for our borders and padding
- aDesiredSize.SetBlockStartAscent(
+ mFirstBaseline =
nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight,
wm.IsLineInverted()) +
- aReflowInput.ComputedLogicalBorderPadding().BStart(wm));
+ aReflowInput.ComputedLogicalBorderPadding().BStart(wm);
+ aDesiredSize.SetBlockStartAscent(mFirstBaseline);
// overflow handling
aDesiredSize.SetOverflowAreasToDesiredBounds();
diff --git a/layout/forms/nsTextControlFrame.h b/layout/forms/nsTextControlFrame.h
index a76cba514..9d4d0b77c 100644
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -62,6 +62,29 @@ public:
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
+ bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
+ nscoord* aBaseline) const override
+ {
+ return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eFirst, aBaseline);
+ }
+
+ bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const override
+ {
+ if (!IsSingleLineTextControl()) {
+ return false;
+ }
+ NS_ASSERTION(mFirstBaseline != NS_INTRINSIC_WIDTH_UNKNOWN,
+ "please call Reflow before asking for the baseline");
+ if (aBaselineGroup == BaselineSharingGroup::eFirst) {
+ *aBaseline = mFirstBaseline;
+ } else {
+ *aBaseline = BSize(aWM) - mFirstBaseline;
+ }
+ return true;
+ }
+
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual bool IsXULCollapsed() override;
@@ -87,6 +110,14 @@ public:
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
+#ifdef DEBUG
+ void MarkIntrinsicISizesDirty() override
+ {
+ // Need another Reflow to have a correct baseline value again.
+ mFirstBaseline = NS_INTRINSIC_WIDTH_UNKNOWN;
+ }
+#endif
+
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
@@ -300,6 +331,10 @@ private:
}
private:
+ // Our first baseline, or NS_INTRINSIC_WIDTH_UNKNOWN if we have a pending
+ // Reflow.
+ nscoord mFirstBaseline;
+
// these packed bools could instead use the high order bits on mState, saving 4 bytes
bool mEditorHasBeenInitialized;
bool mIsProcessing;
diff --git a/layout/forms/test/test_bug562447.html b/layout/forms/test/test_bug562447.html
index 53f84428e..99f691871 100644
--- a/layout/forms/test/test_bug562447.html
+++ b/layout/forms/test/test_bug562447.html
@@ -23,7 +23,7 @@ addLoadEvent(function() {
setTimeout(function() {
// Make sure that we're scrolled by 5000px
- is(window.pageYOffset, 5000, "Make sure we're scrolled correctly");
+ is(Math.round(window.pageYOffset), 5000, "Make sure we're scrolled correctly");
// Scroll back up, and mess with the input box along the way
var input = document.getElementById("WhyDoYouFocusMe");
@@ -38,14 +38,14 @@ addLoadEvent(function() {
window.scrollTo(0, 5000);
setTimeout(function() {
- is(window.pageYOffset, 5000, "Sanity check");
+ is(Math.round(window.pageYOffset), 5000, "Sanity check");
window.scrollTo(0, 0);
input.focus();
input.blur();
setTimeout(function() {
- isnot(window.pageYOffset, 0, "This time we shouldn't be scrolled up");
+ isnot(Math.round(window.pageYOffset), 0, "This time we shouldn't be scrolled up");
SimpleTest.finish();
}, 0);
diff --git a/layout/forms/test/test_bug564115.html b/layout/forms/test/test_bug564115.html
index 5723b55d5..ffd4222ca 100644
--- a/layout/forms/test/test_bug564115.html
+++ b/layout/forms/test/test_bug564115.html
@@ -30,12 +30,12 @@ addLoadEvent(function() {
win.scrollTo(0, 5000);
setTimeout(function() {
- is(win.pageYOffset, 5000, "Page should be scrolled correctly");
+ is(Math.round(win.pageYOffset), 5000, "Page should be scrolled correctly");
// Refocus the window
SimpleTest.waitForFocus(function() {
SimpleTest.waitForFocus(function() {
- is(win.pageYOffset, 5000,
+ is(Math.round(win.pageYOffset), 5000,
"The page's scroll offset should not have been changed");
win.close();
diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp
index 42f4a24b5..a8756cea2 100644
--- a/layout/generic/ReflowInput.cpp
+++ b/layout/generic/ReflowInput.cpp
@@ -93,6 +93,9 @@ ReflowInput::ReflowInput(nsPresContext* aPresContext,
if (aFlags & B_CLAMP_MARGIN_BOX_MIN_SIZE) {
mFlags.mBClampMarginBoxMinSize = true;
}
+ if (aFlags & I_APPLY_AUTO_MIN_SIZE) {
+ mFlags.mApplyAutoMinSize = true;
+ }
if (!(aFlags & CALLER_WILL_INIT)) {
Init(aPresContext);
@@ -242,6 +245,7 @@ ReflowInput::ReflowInput(
mFlags.mIOffsetsNeedCSSAlign = mFlags.mBOffsetsNeedCSSAlign = false;
mFlags.mIClampMarginBoxMinSize = !!(aFlags & I_CLAMP_MARGIN_BOX_MIN_SIZE);
mFlags.mBClampMarginBoxMinSize = !!(aFlags & B_CLAMP_MARGIN_BOX_MIN_SIZE);
+ mFlags.mApplyAutoMinSize = !!(aFlags & I_APPLY_AUTO_MIN_SIZE);
mDiscoveredClearance = nullptr;
mPercentBSizeObserver = (aParentReflowInput.mPercentBSizeObserver &&
@@ -1662,6 +1666,10 @@ ReflowInput::InitAbsoluteConstraints(nsPresContext* aPresContext,
computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
ComputeSizeFlags::eBClampMarginBoxMinSize);
}
+ if (mFlags.mApplyAutoMinSize) {
+ computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
+ ComputeSizeFlags::eIApplyAutoMinSize);
+ }
if (mFlags.mShrinkWrap) {
computeSizeFlags =
ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
@@ -2375,6 +2383,10 @@ ReflowInput::InitConstraints(nsPresContext* aPresContext,
computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
ComputeSizeFlags::eBClampMarginBoxMinSize);
}
+ if (mFlags.mApplyAutoMinSize) {
+ computeSizeFlags = ComputeSizeFlags(computeSizeFlags |
+ ComputeSizeFlags::eIApplyAutoMinSize);
+ }
if (mFlags.mShrinkWrap) {
computeSizeFlags =
ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h
index e42508646..09c980b72 100644
--- a/layout/generic/ReflowInput.h
+++ b/layout/generic/ReflowInput.h
@@ -220,6 +220,7 @@ public:
uint32_t mStaticPosIsCBOrigin:1; // the STATIC_POS_IS_CB_ORIGIN ctor flag
uint32_t mIClampMarginBoxMinSize:1; // the I_CLAMP_MARGIN_BOX_MIN_SIZE ctor flag
uint32_t mBClampMarginBoxMinSize:1; // the B_CLAMP_MARGIN_BOX_MIN_SIZE ctor flag
+ uint32_t mApplyAutoMinSize : 1; // the I_APPLY_AUTO_MIN_SIZE ctor flag
// If set, the following two flags indicate that:
// (1) this frame is absolutely-positioned (or fixed-positioned).
@@ -738,6 +739,9 @@ public:
// Pass ComputeSizeFlags::eBClampMarginBoxMinSize to ComputeSize().
B_CLAMP_MARGIN_BOX_MIN_SIZE = (1<<6),
+
+ // Pass ComputeSizeFlags::eIApplyAutoMinSize to ComputeSize().
+ I_APPLY_AUTO_MIN_SIZE = (1<<7),
};
// This method initializes various data members. It is automatically
diff --git a/layout/generic/Selection.h b/layout/generic/Selection.h
index 6f94303ca..3d5e334fc 100644
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -179,6 +179,9 @@ public:
{
return mRanges.Length();
}
+
+ void GetType(nsAString& aOutType) const;
+
nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv);
void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv);
void RemoveRange(nsRange& aRange, mozilla::ErrorResult& aRv);
diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp
index b61024324..3818d3cb7 100644
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -33,6 +33,8 @@ typedef nsFlexContainerFrame::FlexItem FlexItem;
typedef nsFlexContainerFrame::FlexLine FlexLine;
typedef nsFlexContainerFrame::FlexboxAxisTracker FlexboxAxisTracker;
typedef nsFlexContainerFrame::StrutInfo StrutInfo;
+typedef nsFlexContainerFrame::CachedMeasuringReflowResult
+ CachedMeasuringReflowResult;
static mozilla::LazyLogModule gFlexContainerLog("nsFlexContainerFrame");
@@ -1756,6 +1758,108 @@ nsFlexContainerFrame::
}
}
+/**
+ * A cached result for a measuring reflow.
+ *
+ * Right now we only need to cache the available size and the computed height
+ * for checking that the reflow input is valid, and the height and the ascent
+ * to be used. This can be extended later if needed.
+ *
+ * The assumption here is that a given flex item measurement won't change until
+ * either the available size or computed height changes, or the flex container
+ * intrinsic size is marked as dirty (due to a style or DOM change).
+ *
+ * In particular the computed height may change between measuring reflows due to
+ * how the mIsFlexContainerMeasuringReflow flag affects size computation (see
+ * bug 1336708).
+ *
+ * Caching it prevents us from doing exponential reflows in cases of deeply
+ * nested flex and scroll frames.
+ *
+ * We store them in the frame property table for simplicity.
+ */
+class nsFlexContainerFrame::CachedMeasuringReflowResult
+{
+ // Members that are part of the cache key:
+ const LogicalSize mAvailableSize;
+ const nscoord mComputedHeight;
+
+ // Members that are part of the cache value:
+ const nscoord mHeight;
+ const nscoord mAscent;
+
+public:
+ CachedMeasuringReflowResult(const ReflowInput& aReflowInput,
+ const ReflowOutput& aDesiredSize)
+ : mAvailableSize(aReflowInput.AvailableSize())
+ , mComputedHeight(aReflowInput.ComputedHeight())
+ , mHeight(aDesiredSize.Height())
+ , mAscent(aDesiredSize.BlockStartAscent())
+ {}
+
+ bool IsValidFor(const ReflowInput& aReflowInput) const {
+ return mAvailableSize == aReflowInput.AvailableSize() &&
+ mComputedHeight == aReflowInput.ComputedHeight();
+ }
+
+ nscoord Height() const { return mHeight; }
+
+ nscoord Ascent() const { return mAscent; }
+};
+
+NS_DECLARE_FRAME_PROPERTY_DELETABLE(CachedFlexMeasuringReflow,
+ CachedMeasuringReflowResult);
+
+const CachedMeasuringReflowResult&
+nsFlexContainerFrame::MeasureAscentAndHeightForFlexItem(
+ FlexItem& aItem,
+ nsPresContext* aPresContext,
+ ReflowInput& aChildReflowInput)
+{
+ const FrameProperties props = aItem.Frame()->Properties();
+ if (const auto* cachedResult = props.Get(CachedFlexMeasuringReflow())) {
+ if (cachedResult->IsValidFor(aChildReflowInput)) {
+ return *cachedResult;
+ }
+ }
+
+ ReflowOutput childDesiredSize(aChildReflowInput);
+ nsReflowStatus childReflowStatus;
+
+ const uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
+ ReflowChild(aItem.Frame(), aPresContext,
+ childDesiredSize, aChildReflowInput,
+ 0, 0, flags, childReflowStatus);
+ aItem.SetHadMeasuringReflow();
+
+ // XXXdholbert Once we do pagination / splitting, we'll need to actually
+ // handle incomplete childReflowStatuses. But for now, we give our kids
+ // unconstrained available height, which means they should always complete.
+ MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
+ "We gave flex item unconstrained available height, so it "
+ "should be complete");
+
+ // Tell the child we're done with its initial reflow.
+ // (Necessary for e.g. GetBaseline() to work below w/out asserting)
+ FinishReflowChild(aItem.Frame(), aPresContext,
+ childDesiredSize, &aChildReflowInput, 0, 0, flags);
+
+ auto result =
+ new CachedMeasuringReflowResult(aChildReflowInput, childDesiredSize);
+
+ props.Set(CachedFlexMeasuringReflow(), result);
+ return *result;
+}
+
+/* virtual */ void
+nsFlexContainerFrame::MarkIntrinsicISizesDirty()
+{
+ for (nsIFrame* childFrame : mFrames) {
+ childFrame->Properties().Delete(CachedFlexMeasuringReflow());
+ }
+ nsContainerFrame::MarkIntrinsicISizesDirty();
+}
+
nscoord
nsFlexContainerFrame::
MeasureFlexItemContentHeight(nsPresContext* aPresContext,
@@ -1783,27 +1887,15 @@ nsFlexContainerFrame::
childRIForMeasuringHeight.SetVResize(true);
}
- ReflowOutput childDesiredSize(childRIForMeasuringHeight);
- nsReflowStatus childReflowStatus;
- const uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
- ReflowChild(aFlexItem.Frame(), aPresContext,
- childDesiredSize, childRIForMeasuringHeight,
- 0, 0, flags, childReflowStatus);
-
- MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
- "We gave flex item unconstrained available height, so it "
- "should be complete");
-
- FinishReflowChild(aFlexItem.Frame(), aPresContext,
- childDesiredSize, &childRIForMeasuringHeight,
- 0, 0, flags);
+ const CachedMeasuringReflowResult& reflowResult =
+ MeasureAscentAndHeightForFlexItem(aFlexItem, aPresContext,
+ childRIForMeasuringHeight);
- aFlexItem.SetHadMeasuringReflow();
- aFlexItem.SetAscent(childDesiredSize.BlockStartAscent());
+ aFlexItem.SetAscent(reflowResult.Ascent());
// Subtract border/padding in vertical axis, to get _just_
// the effective computed value of the "height" property.
- nscoord childDesiredHeight = childDesiredSize.Height() -
+ nscoord childDesiredHeight = reflowResult.Height() -
childRIForMeasuringHeight.ComputedPhysicalBorderPadding().TopBottom();
return std::max(0, childDesiredHeight);
@@ -3959,25 +4051,10 @@ nsFlexContainerFrame::SizeItemInCrossAxis(
// whether any of its ancestors are being resized).
aChildReflowInput.SetVResize(true);
}
- ReflowOutput childDesiredSize(aChildReflowInput);
- nsReflowStatus childReflowStatus;
- const uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
- ReflowChild(aItem.Frame(), aPresContext,
- childDesiredSize, aChildReflowInput,
- 0, 0, flags, childReflowStatus);
- aItem.SetHadMeasuringReflow();
-
- // XXXdholbert Once we do pagination / splitting, we'll need to actually
- // handle incomplete childReflowStatuses. But for now, we give our kids
- // unconstrained available height, which means they should always complete.
- MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
- "We gave flex item unconstrained available height, so it "
- "should be complete");
- // Tell the child we're done with its initial reflow.
- // (Necessary for e.g. GetBaseline() to work below w/out asserting)
- FinishReflowChild(aItem.Frame(), aPresContext,
- childDesiredSize, &aChildReflowInput, 0, 0, flags);
+ // Potentially reflow the item, and get the sizing info.
+ const CachedMeasuringReflowResult& reflowResult =
+ MeasureAscentAndHeightForFlexItem(aItem, aPresContext, aChildReflowInput);
// Save the sizing info that we learned from this reflow
// -----------------------------------------------------
@@ -3989,7 +4066,7 @@ nsFlexContainerFrame::SizeItemInCrossAxis(
// so we don't bother with making aAxisTracker pick the cross-axis component
// for us.)
nscoord crossAxisBorderPadding = aItem.GetBorderPadding().TopBottom();
- if (childDesiredSize.Height() < crossAxisBorderPadding) {
+ if (reflowResult.Height() < crossAxisBorderPadding) {
// Child's requested size isn't large enough for its border/padding!
// This is OK for the trivial nsFrame::Reflow() impl, but other frame
// classes should know better. So, if we get here, the child had better be
@@ -4002,10 +4079,10 @@ nsFlexContainerFrame::SizeItemInCrossAxis(
aItem.SetCrossSize(0);
} else {
// (normal case)
- aItem.SetCrossSize(childDesiredSize.Height() - crossAxisBorderPadding);
+ aItem.SetCrossSize(reflowResult.Height() - crossAxisBorderPadding);
}
- aItem.SetAscent(childDesiredSize.BlockStartAscent());
+ aItem.SetAscent(reflowResult.Ascent());
}
void
@@ -4295,7 +4372,7 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
LogicalSize availSize = aReflowInput.ComputedSize(wm);
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput childReflowInput(aPresContext, aReflowInput,
- item->Frame(), availSize);
+ item->Frame(), availSize);
if (!sizeOverride) {
// Directly override the computed main-size, by tweaking reflow state:
if (aAxisTracker.IsMainAxisHorizontal()) {
diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h
index 22b420d85..459ae8e20 100644
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -56,6 +56,7 @@ public:
class FlexLine;
class FlexboxAxisTracker;
struct StrutInfo;
+ class CachedMeasuringReflowResult;
// nsIFrame overrides
void Init(nsIContent* aContent,
@@ -66,6 +67,8 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
+ void MarkIntrinsicISizesDirty() override;
+
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
@@ -195,6 +198,18 @@ protected:
const FlexboxAxisTracker& aAxisTracker);
/**
+ * This method gets a cached measuring reflow for a flex item, or does it and
+ * caches it.
+ *
+ * This avoids exponential reflows, see the comment on
+ * CachedMeasuringReflowResult.
+ */
+ const CachedMeasuringReflowResult& MeasureAscentAndHeightForFlexItem(
+ FlexItem& aItem,
+ nsPresContext* aPresContext,
+ ReflowInput& aChildReflowInput);
+
+ /**
* This method performs a "measuring" reflow to get the content height of
* aFlexItem.Frame() (treating it as if it had auto-height), & returns the
* resulting height.
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index 69791d5c5..418fa16b7 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4781,7 +4781,7 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
ComputeISizeValue(aRenderingContext, aCBSize.ISize(aWM),
boxSizingAdjust.ISize(aWM), boxSizingToMarginEdgeISize,
minISizeCoord, aFlags);
- } else if (MOZ_UNLIKELY(isGridItem)) {
+ } else if (MOZ_UNLIKELY(aFlags & eIApplyAutoMinSize)) {
// This implements "Implied Minimum Size of Grid Items".
// https://drafts.csswg.org/css-grid/#min-size-auto
minISize = std::min(maxISize, GetMinISize(aRenderingContext));
diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp
index 71d5bba21..8f117b5ab 100644
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -818,8 +818,11 @@ struct nsGridContainerFrame::GridItemInfo
// Ditto *-content:[last ]baseline. Mutually exclusive w. eSelfBaseline.
eContentBaseline = 0x10,
eAllBaselineBits = eIsBaselineAligned | eSelfBaseline | eContentBaseline,
+ // Should apply Automatic Minimum Size per:
+ // https://drafts.csswg.org/css-grid/#min-size-auto
+ eApplyAutoMinSize = 0x20,
// Clamp per https://drafts.csswg.org/css-grid/#min-size-auto
- eClampMarginBoxMinSize = 0x20,
+ eClampMarginBoxMinSize = 0x40,
};
explicit GridItemInfo(nsIFrame* aFrame,
@@ -851,11 +854,11 @@ struct nsGridContainerFrame::GridItemInfo
return aAlign;
}
- // Return true if we should we clamp this item's Automatic Minimum Size.
+ // Return true if we should apply Automatic Minimum Size to this item.
// https://drafts.csswg.org/css-grid/#min-size-auto
- bool ShouldClampMinSize(WritingMode aContainerWM,
- LogicalAxis aContainerAxis,
- nscoord aPercentageBasis) const
+ bool ShouldApplyAutoMinSize(WritingMode aContainerWM,
+ LogicalAxis aContainerAxis,
+ nscoord aPercentageBasis) const
{
const auto pos = mFrame->StylePosition();
const auto& size = aContainerAxis == eLogicalAxisInline ?
@@ -2090,6 +2093,18 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput
SizingConstraint aConstraint);
/**
+ * Return the percentage basis for a grid item in its writing-mode.
+ * If aAxis is eLogicalAxisInline then we return NS_UNCONSTRAINEDSIZE in
+ * both axes since we know all track sizes are indefinite at this point
+ * (we calculate column sizes before row sizes). Otherwise, assert that
+ * column sizes are known and calculate the size for aGridItem.mArea.mCols
+ * and use NS_UNCONSTRAINEDSIZE in the other axis.
+ * @param aAxis the axis we're currently calculating track sizes for
+ */
+ LogicalSize PercentageBasisFor(LogicalAxis aAxis,
+ const GridItemInfo& aGridItem) const;
+
+ /**
* Return the containing block for a grid item occupying aArea.
*/
LogicalRect ContainingBlockFor(const GridArea& aArea) const;
@@ -3731,18 +3746,20 @@ MeasuringReflow(nsIFrame* aChild,
* the child's margin-box) in aAxis.
*/
static nscoord
-ContentContribution(const GridItemInfo& aGridItem,
- const GridReflowInput& aState,
- nsRenderingContext* aRC,
- WritingMode aCBWM,
- LogicalAxis aAxis,
- IntrinsicISizeType aConstraint,
- nscoord aMinSizeClamp = NS_MAXSIZE,
- uint32_t aFlags = 0)
+ContentContribution(const GridItemInfo& aGridItem,
+ const GridReflowInput& aState,
+ nsRenderingContext* aRC,
+ WritingMode aCBWM,
+ LogicalAxis aAxis,
+ const Maybe<LogicalSize>& aPercentageBasis,
+ IntrinsicISizeType aConstraint,
+ nscoord aMinSizeClamp = NS_MAXSIZE,
+ uint32_t aFlags = 0)
{
nsIFrame* child = aGridItem.mFrame;
PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis));
nscoord size = nsLayoutUtils::IntrinsicForAxis(axis, aRC, child, aConstraint,
+ aPercentageBasis,
aFlags | nsLayoutUtils::BAIL_IF_REFLOW_NEEDED |
nsLayoutUtils::ADD_PERCENTS,
aMinSizeClamp);
@@ -3812,6 +3829,10 @@ struct CachedIntrinsicSizes
Maybe<nscoord> mMinSize;
Maybe<nscoord> mMinContentContribution;
Maybe<nscoord> mMaxContentContribution;
+
+ // The item's percentage basis for intrinsic sizing purposes.
+ Maybe<LogicalSize> mPercentageBasis;
+
// "if the grid item spans only grid tracks that have a fixed max track
// sizing function, its automatic minimum size in that dimension is
// further clamped to less than or equal to the size necessary to fit its
@@ -3832,7 +3853,11 @@ MinContentContribution(const GridItemInfo& aGridItem,
if (aCache->mMinContentContribution.isSome()) {
return aCache->mMinContentContribution.value();
}
+ if (aCache->mPercentageBasis.isNothing()) {
+ aCache->mPercentageBasis.emplace(aState.PercentageBasisFor(aAxis, aGridItem));
+ }
nscoord s = ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
+ aCache->mPercentageBasis,
nsLayoutUtils::MIN_ISIZE,
aCache->mMinSizeClamp);
aCache->mMinContentContribution.emplace(s);
@@ -3850,7 +3875,11 @@ MaxContentContribution(const GridItemInfo& aGridItem,
if (aCache->mMaxContentContribution.isSome()) {
return aCache->mMaxContentContribution.value();
}
+ if (aCache->mPercentageBasis.isNothing()) {
+ aCache->mPercentageBasis.emplace(aState.PercentageBasisFor(aAxis, aGridItem));
+ }
nscoord s = ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
+ aCache->mPercentageBasis,
nsLayoutUtils::PREF_ISIZE,
aCache->mMinSizeClamp);
aCache->mMaxContentContribution.emplace(s);
@@ -3904,7 +3933,11 @@ MinSize(const GridItemInfo& aGridItem,
child->StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)) {
// Now calculate the "content size" part and return whichever is smaller.
MOZ_ASSERT(unit != eStyleUnit_Enumerated || sz == NS_UNCONSTRAINEDSIZE);
+ if (aCache->mPercentageBasis.isNothing()) {
+ aCache->mPercentageBasis.emplace(aState.PercentageBasisFor(aAxis, aGridItem));
+ }
sz = std::min(sz, ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
+ aCache->mPercentageBasis,
nsLayoutUtils::MIN_ISIZE,
aCache->mMinSizeClamp,
nsLayoutUtils::MIN_INTRINSIC_ISIZE));
@@ -3977,9 +4010,9 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSizeStep1(
WritingMode wm = aState.mWM;
// Calculate data for "Automatic Minimum Size" clamping, if needed.
bool needed = ((sz.mState & TrackSize::eIntrinsicMinSizing) ||
- aConstraint == SizingConstraint::eNoConstraint);
- if (needed && TrackSize::IsDefiniteMaxSizing(sz.mState) &&
- aGridItem.ShouldClampMinSize(wm, mAxis, aPercentageBasis)) {
+ aConstraint == SizingConstraint::eNoConstraint) &&
+ (aGridItem.mState[mAxis] & ItemState::eApplyAutoMinSize);
+ if (needed && TrackSize::IsDefiniteMaxSizing(sz.mState)) {
if (sz.mState & TrackSize::eIntrinsicMinSizing) {
auto maxCoord = aFunctions.MaxSizingFor(aRange.mStart);
cache.mMinSizeClamp =
@@ -4382,6 +4415,14 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
iter.Reset();
for (; !iter.AtEnd(); iter.Next()) {
auto& gridItem = aGridItems[iter.GridItemIndex()];
+
+ // Check if we need to apply "Automatic Minimum Size" and cache it.
+ MOZ_ASSERT(!(gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize),
+ "Why is eApplyAutoMinSize set already?");
+ if (gridItem.ShouldApplyAutoMinSize(wm, mAxis, aPercentageBasis)) {
+ gridItem.mState[mAxis] |= ItemState::eApplyAutoMinSize;
+ }
+
const GridArea& area = gridItem.mArea;
const LineRange& lineRange = area.*aRange;
uint32_t span = lineRange.Extent();
@@ -4407,9 +4448,9 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
CachedIntrinsicSizes cache;
// Calculate data for "Automatic Minimum Size" clamping, if needed.
bool needed = ((state & TrackSize::eIntrinsicMinSizing) ||
- aConstraint == SizingConstraint::eNoConstraint);
- if (needed && TrackSize::IsDefiniteMaxSizing(state) &&
- gridItem.ShouldClampMinSize(wm, mAxis, aPercentageBasis)) {
+ aConstraint == SizingConstraint::eNoConstraint) &&
+ (gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize);
+ if (needed && TrackSize::IsDefiniteMaxSizing(state)) {
nscoord minSizeClamp = 0;
for (auto i = lineRange.mStart, end = lineRange.mEnd; i < end; ++i) {
auto maxCoord = aFunctions.MaxSizingFor(i);
@@ -4445,11 +4486,14 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
gridItem.mState[mAxis] |= ItemState::eIsFlexing;
} else if (aConstraint == SizingConstraint::eNoConstraint &&
TrackSize::IsDefiniteMaxSizing(state) &&
- gridItem.ShouldClampMinSize(wm, mAxis, aPercentageBasis)) {
+ (gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize)) {
gridItem.mState[mAxis] |= ItemState::eClampMarginBoxMinSize;
}
}
}
+ MOZ_ASSERT(!(gridItem.mState[mAxis] & ItemState::eClampMarginBoxMinSize) ||
+ (gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize),
+ "clamping only applies to Automatic Minimum Size");
}
// Step 2.
@@ -4707,7 +4751,8 @@ nsGridContainerFrame::Tracks::FindUsedFlexFraction(
const GridItemInfo& item = aGridItems[iter.GridItemIndex()];
if (item.mState[mAxis] & ItemState::eIsFlexing) {
// XXX optimize: bug 1194446
- nscoord spaceToFill = ContentContribution(item, aState, rc, wm, mAxis,
+ auto pb = Some(aState.PercentageBasisFor(mAxis, item));
+ nscoord spaceToFill = ContentContribution(item, aState, rc, wm, mAxis, pb,
nsLayoutUtils::PREF_ISIZE);
if (spaceToFill <= 0) {
continue;
@@ -5038,6 +5083,25 @@ nsGridContainerFrame::LineRange::ToPositionAndLengthForAbsPos(
}
}
+LogicalSize
+nsGridContainerFrame::GridReflowInput::PercentageBasisFor(
+ LogicalAxis aAxis,
+ const GridItemInfo& aGridItem) const
+{
+ auto wm = aGridItem.mFrame->GetWritingMode();
+ if (aAxis == eLogicalAxisInline) {
+ return LogicalSize(wm, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
+ }
+ // Note: for now, we only resolve transferred percentages to row sizing.
+ // We may need to adjust these assertions once we implement bug 1300366.
+ MOZ_ASSERT(mCols.mCanResolveLineRangeSize);
+ MOZ_ASSERT(!mRows.mCanResolveLineRangeSize);
+ nscoord colSize = aGridItem.mArea.mCols.ToLength(mCols.mSizes);
+ nscoord rowSize = NS_UNCONSTRAINEDSIZE;
+ return !wm.IsOrthogonalTo(mWM) ?
+ LogicalSize(wm, colSize, rowSize) : LogicalSize(wm, rowSize, colSize);
+}
+
LogicalRect
nsGridContainerFrame::GridReflowInput::ContainingBlockFor(const GridArea& aArea) const
{
@@ -5231,6 +5295,9 @@ nsGridContainerFrame::ReflowInFlowChild(nsIFrame* aChild,
} else {
aChild->Properties().Delete(BClampMarginBoxMinSizeProperty());
}
+ if ((aGridItemInfo->mState[childIAxis] & ItemState::eApplyAutoMinSize)) {
+ flags |= ReflowInput::I_APPLY_AUTO_MIN_SIZE;
+ }
}
if (!isConstrainedBSize) {
diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h
index 50eb958e0..2acafa882 100644
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2105,6 +2105,14 @@ public:
*/
eIClampMarginBoxMinSize = 1 << 2, // clamp in our inline axis
eBClampMarginBoxMinSize = 1 << 3, // clamp in our block axis
+ /**
+ * The frame is stretching (per CSS Box Alignment) and doesn't have an
+ * Automatic Minimum Size in the indicated axis.
+ * (may be used for both flex/grid items, but currently only used for Grid)
+ * https://drafts.csswg.org/css-grid/#min-size-auto
+ * https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
+ */
+ eIApplyAutoMinSize = 1 << 4, // only has an effect when eShrinkWrap is false
};
/**
diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp
index e0d65632e..a2227c39c 100644
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -5349,6 +5349,18 @@ Selection::GetRangeCount(int32_t* aRangeCount)
return NS_OK;
}
+void
+Selection::GetType(nsAString& aOutType) const
+{
+ if (!RangeCount()) {
+ aOutType.AssignLiteral("None");
+ } else if (IsCollapsed()) {
+ aOutType.AssignLiteral("Caret");
+ } else {
+ aOutType.AssignLiteral("Range");
+ }
+}
+
NS_IMETHODIMP
Selection::GetRangeAt(int32_t aIndex, nsIDOMRange** aReturn)
{
diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp
index b9848bcf1..00c0016fd 100644
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -9751,9 +9751,13 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset,
startOffset = aStartOffset;
endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset);
}
+
+ // If startOffset and/or endOffset are inside of trimmedOffsets' range,
+ // then clamp the edges of trimmedOffsets accordingly.
+ int32_t origTrimmedOffsetsEnd = trimmedOffsets.GetEnd();
trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart,
startOffset);
- trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(),
+ trimmedOffsets.mLength = std::min<uint32_t>(origTrimmedOffsetsEnd,
endOffset) - trimmedOffsets.mStart;
if (trimmedOffsets.mLength <= 0) {
offsetInRenderedString = nextOffsetInRenderedString;
diff --git a/layout/printing/nsPagePrintTimer.cpp b/layout/printing/nsPagePrintTimer.cpp
index b56569a9a..164b0469a 100644
--- a/layout/printing/nsPagePrintTimer.cpp
+++ b/layout/printing/nsPagePrintTimer.cpp
@@ -14,14 +14,8 @@ NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, mozilla::Runnable, nsITimerCallbac
nsPagePrintTimer::~nsPagePrintTimer()
{
- // "Destroy" the document viewer; this normally doesn't actually
- // destroy it because of the IncrementDestroyRefCount call below
- // XXX This is messy; the document viewer should use a single approach
- // to keep itself alive during printing
- nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint));
- if (cv) {
- cv->Destroy();
- }
+ // This matches the IncrementDestroyRefCount call in the constructor.
+ mDocViewerPrint->DecrementDestroyRefCount();
}
nsresult
diff --git a/layout/reftests/bugs/315920-17.html b/layout/reftests/bugs/315920-17.html
index 1681754a5..6d9180144 100644
--- a/layout/reftests/bugs/315920-17.html
+++ b/layout/reftests/bugs/315920-17.html
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html>
+<html class="reftest-wait">
<head>
<style>
input ~ label {color: red}
@@ -8,9 +8,7 @@
input:checked:default + label {color: green}
</style>
</head>
- <body onload='document.getElementById("two").setAttribute("checked", "true");
- document.getElementById("one").setAttribute("checked", "checked");
- document.getElementById("two").removeAttribute("checked");'>
+ <body>
<form>
<input type="checkbox" name="group1" id="one" value="1"/>
<label for="one">Should be no red</label><br>
@@ -19,5 +17,14 @@
<input type="checkbox" name="group1" id="three" value="3"/>
<label for="three">Should be no red</label>
</form>
+<script>
+function doTest() {
+ document.getElementById("two").setAttribute("checked", "true");
+ document.getElementById("one").setAttribute("checked", "checked");
+ document.getElementById("two").removeAttribute("checked");
+ setTimeout(function () { document.documentElement.removeAttribute("class"); }, 0);
+}
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
</body>
</html>
diff --git a/layout/reftests/css-grid/grid-auto-min-sizing-min-content-min-size-004-ref.html b/layout/reftests/css-grid/grid-auto-min-sizing-min-content-min-size-004-ref.html
index fc74cd214..caef8b031 100644
--- a/layout/reftests/css-grid/grid-auto-min-sizing-min-content-min-size-004-ref.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-min-content-min-size-004-ref.html
@@ -36,7 +36,7 @@ var rowtest = [
"min-width:80%; max-height:20px", "min-width:50%", "margin-left: 50px; width:50%"
];
var results = [
-"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "24px/2px", "20px/2px", "20px/2px", "24px/2px", "24px/52px"
+"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "12px/2px", "20px/2px", "20px/2px", "24px/2px", "24px/52px"
];
var item_height = [
"0", "0", "0", "0", "0", "0", "12px", "20px", "20px", "24px", "312px"
diff --git a/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-004-ref.html b/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-004-ref.html
index c5d8a68ff..36a2d4920 100644
--- a/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-004-ref.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-transferred-size-004-ref.html
@@ -36,7 +36,7 @@ var rowtest = [
"min-width:80%; max-height:20px", "min-width:50%", "margin-left: 50px; width:50%"
];
var results = [
-"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "24px/2px", "20px/2px", "20px/2px", "24px/2px", "24px/52px"
+"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "12px/2px", "20px/2px", "20px/2px", "24px/2px", "24px/52px"
];
var item_height = [
"0", "0", "0", "0", "0", "0", "12px", "20px", "20px", "24px", "312px"
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-001-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-001-ref.html
new file mode 100644
index 000000000..463bbb4e6
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-001-ref.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: stretching overflow!=visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px 30px 3px / 7px 80px 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ min-width:0;
+ min-height:0;
+ box-sizing: border-box;
+}
+
+.oa, .os, .oh { width:80px; height:30px; }
+.m.oa, .m.os, .m.oh { width:70px; height:24px; }
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" " style="width:112px"><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m " style="width:112px"><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" " style="height:112px"><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m " style="height:112px"><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-001.html b/layout/reftests/css-grid/grid-item-overflow-stretch-001.html
new file mode 100644
index 000000000..4f6259abe
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-001.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: stretching overflow!=visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-001-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+}
+
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-002-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-002-ref.html
new file mode 100644
index 000000000..a9690a54e
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-002-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: stretching overflow!=visible vertical-rl items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px 30px 3px / 7px 80px 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ writing-mode: vertical-rl;
+ min-width:0;
+ min-height:0;
+ box-sizing: border-box;
+}
+
+.oa, .os, .oh { width:80px; height:30px; }
+.m.oa, .m.os, .m.oh { width:70px; height:24px; }
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" " style="width:112px"><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m " style="width:112px"><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" " style="height:112px"><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m " style="height:112px"><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-002.html b/layout/reftests/css-grid/grid-item-overflow-stretch-002.html
new file mode 100644
index 000000000..520eed911
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-002.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: stretching overflow!=visible vertical-rl items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-002-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ writing-mode: vertical-rl;
+}
+
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-003-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-003-ref.html
new file mode 100644
index 000000000..c082e6be4
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-003-ref.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: margin:auto stretch items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px 30px 3px / 7px 112px 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+.c2 { grid-template-columns: 7px 122px 3px; }
+.h > .grid { grid: 7px 112px 3px / 7px 80px 3px; }
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ margin: 0 auto;
+ justify-self:start;
+ align-self:start;
+ height:28px;
+}
+.c2 > * { height:22px; }
+.h .grid > * {
+ margin: 10px 0 0 10px;
+ justify-self:center;
+ align-self:center;
+ width:5px;
+ height:110px;
+}
+
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid c2"><span class="m oa"><x></x></span></div>
+<div class="grid c2"><span class="m os"><x></x></span></div>
+<div class="grid c2"><span class="m oh"><x></x></span></div>
+<div class="grid c2"><span class="m "><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-003.html b/layout/reftests/css-grid/grid-item-overflow-stretch-003.html
new file mode 100644
index 000000000..8bcd79d9b
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-003.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: margin:auto stretch items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-003-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ margin: 0 auto;
+}
+.h .grid > * {
+ margin: auto;
+}
+
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="oa"><x></x></span></div>
+<div class="grid"><span class="os"><x></x></span></div>
+<div class="grid"><span class="oh"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m oa"><x></x></span></div>
+<div class="grid"><span class="m os"><x></x></span></div>
+<div class="grid"><span class="m oh"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-004-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-004-ref.html
new file mode 100644
index 000000000..71ed28d7c
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-004-ref.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: stretching items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 90px;
+ height: 50px;
+ grid: 7px 30px 3px / 7px 102px 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+.c2 { grid: 7px 30x 3px / 7px 112px 3px; grid-gap: 5px;}
+.c3 { grid: 7px 30x 3px / 7px 70px 3px; grid-gap: 5px;}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ min-width: 0;
+ max-width: 100px;
+}
+.h .grid > * {
+ min-height: 0;
+ max-height: 100px;
+ justify-self:center safe;
+ align-self:center safe;
+}
+.h > .grid { grid: 7px 102px 3px / 7px 70px 3px; grid-gap: 5px;}
+.h > .grid.c2 { grid: 7px 30px 3px / 7px 70px 3px; grid-gap: 5px;}
+.h > .grid.c3 { grid: 7px 108px 3px / 7px 70px 3px; grid-gap: 5px;}
+
+.oa { overflow: auto; }
+.p { width: 100%; }
+.h .grid > .p { height: 100%; }
+.x { width:5px; }
+.h .grid > .x { max-height:5px; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="p oa"><x></x></span></div>
+<div class="grid"><span class="p "><x></x></span></div>
+<div class="grid c2"><span class="p x" style="height:5px; margin-left:31.5px; margin-top:11.5px"><x></x></span></div>
+<div class="grid c2"><span class=" " style="width:68px"><x></x></span></div>
+
+<br>
+
+<div class="grid c3"><span class="p m oa"><x></x></span></div>
+<div class="grid c3"><span class="p m"><x></x></span></div>
+<div class="grid c2"><span class="m p x"><x></x></span></div>
+<div class="grid c2"><span class="m " style="width:58px"><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="p oa"><x></x></span></div>
+<div class="grid"><span class="p "><x></x></span></div>
+<div class="grid c2"><span class="p x" style=""><x></x></span></div>
+<div class="grid c2"><span class=" " style="height:28px; width:68px;"><x></x></span></div>
+
+<br>
+
+<div class="grid c3"><span class="m p oa"><x></x></span></div>
+<div class="grid c3"><span class="m p"><x></x></span></div>
+<div class="grid c2"><span class="m p x" style="justify-self:start;align-self:start"><x></x></span></div>
+<div class="grid c2"><span class="m " style="height:22px; width:58px"><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-004.html b/layout/reftests/css-grid/grid-item-overflow-stretch-004.html
new file mode 100644
index 000000000..b983b5184
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-004.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: stretching items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-004-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 90px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ min-width: 0;
+ max-width: 100px;
+}
+.h .grid > * {
+ min-height: 0;
+ max-height: 100px;
+}
+
+.oa { overflow: auto; }
+.p { width: 100%; }
+.h .grid > .p { height: 100%; }
+.x { max-width:5px; margin:auto; }
+.h .grid > .x { max-height:5px; }
+.m { margin: 1px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class="p oa"><x></x></span></div>
+<div class="grid"><span class="p "><x></x></span></div>
+<div class="grid"><span class="p x"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="p m oa"><x></x></span></div>
+<div class="grid"><span class="p m"><x></x></span></div>
+<div class="grid"><span class="m p x"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="p oa"><x></x></span></div>
+<div class="grid"><span class="p "><x></x></span></div>
+<div class="grid"><span class="p x"><x></x></span></div>
+<div class="grid"><span class=" "><x></x></span></div>
+
+<br>
+
+<div class="grid"><span class="m p oa"><x></x></span></div>
+<div class="grid"><span class="m p"><x></x></span></div>
+<div class="grid"><span class="m p x"><x></x></span></div>
+<div class="grid"><span class="m "><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-005-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-005-ref.html
new file mode 100644
index 000000000..e7d353c8b
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-005-ref.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: stretching overflow!=visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ min-width:0;
+ min-height:0;
+ box-sizing: border-box;
+}
+
+.oa, .os, .oh { width:80px; height:30px; }
+.m.oa, .m.os, .m.oh { width:70px; height:8px; }
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.ov { justify-self: start; }
+.m.ov { align-self: start; }
+.m { margin: 17px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><input class="oa"></div>
+<div class="grid"><input class="os"></div>
+<div class="grid"><input class="oh"></div>
+<div class="grid"><input class="ov"></div>
+
+<br>
+
+<div class="grid"><input class="m oa"></div>
+<div class="grid"><input class="m os"></div>
+<div class="grid"><input class="m oh"></div>
+<div class="grid"><input class="m ov"></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><input class="oa"></div>
+<div class="grid"><input class="os"></div>
+<div class="grid"><input class="oh"></div>
+<div class="grid"><input class="ov"></div>
+
+<br>
+
+<div class="grid"><input class="m oa"></div>
+<div class="grid"><input class="m os"></div>
+<div class="grid"><input class="m oh"></div>
+<div class="grid"><input class="m ov"></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-005.html b/layout/reftests/css-grid/grid-item-overflow-stretch-005.html
new file mode 100644
index 000000000..33fe468d7
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-005.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: stretching overflow!=visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-005-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px auto 3px / 7px auto 3px;
+ grid-gap: 5px;
+ border:1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border:1px solid;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+}
+
+.oa { overflow: auto; }
+.os { overflow: scroll; }
+.oh { overflow: hidden; }
+.m { margin: 17px 3px 5px 7px; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><input class="oa"></div>
+<div class="grid"><input class="os"></div>
+<div class="grid"><input class="oh"></div>
+<div class="grid"><input class=" "></div>
+
+<br>
+
+<div class="grid"><input class="m oa"></div>
+<div class="grid"><input class="m os"></div>
+<div class="grid"><input class="m oh"></div>
+<div class="grid"><input class="m "></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><input class="oa"></div>
+<div class="grid"><input class="os"></div>
+<div class="grid"><input class="oh"></div>
+<div class="grid"><input class=" "></div>
+
+<br>
+
+<div class="grid"><input class="m oa"></div>
+<div class="grid"><input class="m os"></div>
+<div class="grid"><input class="m oh"></div>
+<div class="grid"><input class="m "></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html b/layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html
new file mode 100644
index 000000000..71d4d4f54
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Reference: stretching overflow visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-flex;
+ width: 90px;
+ height: 40px;
+ padding: 7px 3px 3px 7px;
+ border: 1px solid;
+}
+
+.grid > * {
+ border: 1px solid;
+ margin: 5px;
+}
+
+.m { margin: 6px 8px 10px 12px; }
+.ma { margin: auto; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class=""><x></x></span></div>
+<div class="grid"><span class="m"><x></x></span></div>
+<div class="grid"><span class="ma" style="margin-left:5px"><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class="" style="flex:1"><x></x></span></div>
+<div class="grid"><span class="m" style="flex:1"><x></x></span></div>
+<div class="grid"><span class="ma" style="margin-top:5px"><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-item-overflow-stretch-006.html b/layout/reftests/css-grid/grid-item-overflow-stretch-006.html
new file mode 100644
index 000000000..015c50fcc
--- /dev/null
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-006.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Grid Test: stretching overflow visible items</title>
+ <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1348857">
+ <link rel="match" href="grid-item-overflow-stretch-006-ref.html">
+ <style type="text/css">
+body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+
+.grid {
+ display: inline-grid;
+ width: 100px;
+ height: 50px;
+ grid: 7px minmax(20px, auto) 3px / 7px minmax(20px, auto) 3px;
+ grid-gap: 5px;
+ border: 1px solid;
+}
+
+.grid > * {
+ grid-area: 2/2;
+ border: 1px solid;
+}
+
+.m { margin: 1px 3px 5px 7px; }
+.ma { margin: auto; }
+
+x { display:block; width:110px; height:5px; background:grey; }
+.h .grid x { width:5px; height:110px; }
+
+br { clear:both; }
+ </style>
+</head>
+<body>
+
+<div class="grid"><span class=""><x></x></span></div>
+<div class="grid"><span class="m"><x></x></span></div>
+<div class="grid"><span class="ma"><x></x></span></div>
+
+<br>
+
+<div class="h">
+
+<div class="grid"><span class=""><x></x></span></div>
+<div class="grid"><span class="m"><x></x></span></div>
+<div class="grid"><span class="ma"><x></x></span></div>
+
+<br>
+
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/css-grid/grid-min-content-min-sizing-transferred-size-004-ref.html b/layout/reftests/css-grid/grid-min-content-min-sizing-transferred-size-004-ref.html
index 5fa60b3b5..04d047b83 100644
--- a/layout/reftests/css-grid/grid-min-content-min-sizing-transferred-size-004-ref.html
+++ b/layout/reftests/css-grid/grid-min-content-min-sizing-transferred-size-004-ref.html
@@ -36,7 +36,7 @@ var rowtest = [
"min-width:80%; max-height:20px", "min-width:50%", "margin-left: 50px; width:50%"
];
var results = [
-"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "24px/2px", "20px/2px", "20px/2px", "24px/2px", "24px/52px"
+"0/2px", "0/2px", "0/4px", "0/2px", "0/2px", "0/2px", "12px/2px", "20px/2px", "20px/2px", "24px/2px", "312px/52px"
];
var item_height = [
"0", "0", "0", "0", "0", "0", "12px", "20px", "20px", "24px", "312px"
diff --git a/layout/reftests/css-grid/reftest.list b/layout/reftests/css-grid/reftest.list
index d85eefbd0..093e2faee 100644
--- a/layout/reftests/css-grid/reftest.list
+++ b/layout/reftests/css-grid/reftest.list
@@ -116,6 +116,12 @@ skip-if(Android) == grid-auto-min-sizing-percent-001.html grid-auto-min-sizing-p
== grid-item-auto-min-size-clamp-005.html grid-item-auto-min-size-clamp-005-ref.html
== grid-item-auto-min-size-clamp-006.html grid-item-auto-min-size-clamp-006-ref.html
== grid-item-auto-min-size-clamp-007.html grid-item-auto-min-size-clamp-007-ref.html
+== grid-item-overflow-stretch-001.html grid-item-overflow-stretch-001-ref.html
+== grid-item-overflow-stretch-002.html grid-item-overflow-stretch-002-ref.html
+== grid-item-overflow-stretch-003.html grid-item-overflow-stretch-003-ref.html
+== grid-item-overflow-stretch-004.html grid-item-overflow-stretch-004-ref.html
+== grid-item-overflow-stretch-005.html grid-item-overflow-stretch-005-ref.html
+== grid-item-overflow-stretch-006.html grid-item-overflow-stretch-006-ref.html
== grid-item-canvas-001.html grid-item-canvas-001-ref.html
skip-if(Android) == grid-item-button-001.html grid-item-button-001-ref.html
== grid-item-table-stretch-001.html grid-item-table-stretch-001-ref.html
diff --git a/layout/reftests/forms/display-block-baselines-1-ref.html b/layout/reftests/forms/display-block-baselines-1-ref.html
new file mode 100644
index 000000000..d01c086b5
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-1-ref.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Testcase #1 for bug 1330962</title>
+ <style type="text/css">
+@font-face {
+ src: url(../fonts/Ahem.ttf);
+ font-family: Ahem;
+}
+html,body {
+ color:black; background-color:white; font:16px/1 Ahem; padding:0; margin:0;
+}
+* { font:16px/1 Ahem; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-grid">
+ A<img class="block" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAEElEQVQoz2NgGAWjYBTAAAADEAABaJFtwwAAAABJRU5ErkJggg%3D%3D">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <input type="image" class="block" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAEElEQVQoz2NgGAWjYBTAAAADEAABaJFtwwAAAABJRU5ErkJggg%3D%3D">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><input type="text" value="text"></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><input type="text" value="text"></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><input type="text"></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><input class="no-theme" type="text" value="text"></div>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-1.html b/layout/reftests/forms/display-block-baselines-1.html
new file mode 100644
index 000000000..96ebdad71
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-1.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase #1 for bug 1330962</title>
+ <style type="text/css">
+@font-face {
+ src: url(../fonts/Ahem.ttf);
+ font-family: Ahem;
+}
+html,body {
+ color:black; background-color:white; font:16px/1 Ahem; padding:0; margin:0;
+}
+* { font:16px/1 Ahem; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <img class="block" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAEElEQVQoz2NgGAWjYBTAAAADEAABaJFtwwAAAABJRU5ErkJggg%3D%3D">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input type="image" class="block" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAEElEQVQoz2NgGAWjYBTAAAADEAABaJFtwwAAAABJRU5ErkJggg%3D%3D">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block" type="text" value="text">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block scroll" type="text" value="text">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block" type="text">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block no-theme" type="text" value="text">
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-2-ref.html b/layout/reftests/forms/display-block-baselines-2-ref.html
new file mode 100644
index 000000000..441a927b4
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-2-ref.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Testcase #2 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+ color: black;
+ text-align: start;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A<div>
+ <div style="display:inline-block"><input type="button" value="button"></div></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><button>button</button></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><input class="no-theme" type="button" value="button"></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <button class="no-theme">button-first<div style="font-size:10px">button-last</div></button>
+ </div>
+ B
+ <div class="no-theme" style="display:inline-block">button-first<div style="font-size:10px">button-last</div></div>
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <button class="no-theme" style="display:inline-grid">button-first<x style="font-size:10px">button-last</x></button>
+ </div>
+ B
+ <div class="no-theme" style="display:inline-grid">button-first<x style="font-size:10px">button-last</x></div>
+</div>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <input type="checkbox" class="block" checked>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <input type="radio" class="block" checked>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-2.html b/layout/reftests/forms/display-block-baselines-2.html
new file mode 100644
index 000000000..78253fe4c
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-2.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase #2 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+ color: black;
+ text-align: start;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block" type="button" value="button">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <button class="block">button</button>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input class="block no-theme" type="button" value="button">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <button class="block no-theme">button-first<div style="font-size:10px">button-last</div></button>
+ </div>
+ B
+ <button class="no-theme">button-first<div style="font-size:10px">button-last</div></button>
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <button class="grid no-theme">button-first<x style="font-size:10px">button-last</x></button>
+ </div>
+ B
+ <button class="no-theme" style="display:inline-grid">button-first<x style="font-size:10px">button-last</x></button>
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input type="checkbox" class="block" checked>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input type="radio" class="block" checked>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-3-ref.html b/layout/reftests/forms/display-block-baselines-3-ref.html
new file mode 100644
index 000000000..ce277b50c
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-3-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Testcase #3 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <textarea class="block">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <textarea class="block no-theme">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-grid">
+ A
+ <textarea class="block no-theme no-scroll">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><fieldset style="display:inline">fieldset-first<br>fieldset-last</fieldset></div>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-3.html b/layout/reftests/forms/display-block-baselines-3.html
new file mode 100644
index 000000000..9f3c2b110
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-3.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase #3 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <textarea class="block">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <textarea class="block no-theme">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <textarea class="block no-theme no-scroll">textarea</textarea>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <fieldset class="block">fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-4-ref.html b/layout/reftests/forms/display-block-baselines-4-ref.html
new file mode 100644
index 000000000..5015d50c4
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-4-ref.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Testcase #4 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <div style="display:inline-block"><fieldset style="display:inline"><legend>legend</legend>
+fieldset-first<br>fieldset-last</fieldset></div>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <fieldset style="display:inline-grid">grid-fieldset-first<x>grid-fieldset-last</x></fieldset>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <fieldset style="display:inline" class="no-theme">fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <fieldset style="display:inline" class="no-theme scroll">fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-4.html b/layout/reftests/forms/display-block-baselines-4.html
new file mode 100644
index 000000000..1bfd344b0
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-4.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase #4 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <fieldset class="block"><legend>legend</legend>
+fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <fieldset class="grid"><x style="order:2">grid-fieldset-last</x>grid-fieldset-first</fieldset>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <fieldset class="block no-theme">fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <fieldset class="block no-theme scroll">fieldset-first<br>fieldset-last</fieldset>
+ </div>
+ B
+</div>
+
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-5-ref.html b/layout/reftests/forms/display-block-baselines-5-ref.html
new file mode 100644
index 000000000..0dce47f59
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-5-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Testcase #5 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <input type="color">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <input type="color" class="no-theme">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <select><option>select</select>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A<br>
+ <select class="no-theme"><option>select</select>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/display-block-baselines-5.html b/layout/reftests/forms/display-block-baselines-5.html
new file mode 100644
index 000000000..0359c8a6f
--- /dev/null
+++ b/layout/reftests/forms/display-block-baselines-5.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Testcase #5 for bug 1330962</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+* { font:16px/1 monospace; }
+
+.block { display: block; }
+.grid { display: grid; }
+
+.no-theme {
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ padding: 20px 0;
+ border: none;
+ background: white;
+}
+
+.scroll {
+ overflow-y: scroll;
+}
+
+.no-scroll {
+ overflow: visible;
+}
+
+ </style>
+</head>
+<body>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input type="color" class="block">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <input type="color" class="block no-theme">
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <select class="block"><option>select</select>
+ </div>
+ B
+</div>
+
+<div>
+ <div style="display:inline-block">
+ A
+ <select class="block no-theme"><option>select</select>
+ </div>
+ B
+</div>
+
+</body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/reftest.list b/layout/reftests/forms/input/datetime/reftest.list
index 0ce2002bd..a62d56c7c 100644
--- a/layout/reftests/forms/input/datetime/reftest.list
+++ b/layout/reftests/forms/input/datetime/reftest.list
@@ -11,3 +11,14 @@ skip-if(!Android&&!B2G&&!Mulet) == time-simple-unthemed.html time-simple-untheme
# type change
skip-if(Android||B2G||Mulet) == to-time-from-other-type-unthemed.html time-simple-unthemed.html
skip-if(Android||B2G||Mulet) == from-time-to-other-type-unthemed.html from-time-to-other-type-unthemed-ref.html
+
+# content should not overflow on small width/height
+skip-if(Android) == time-small-width.html time-small-width-ref.html
+skip-if(Android) == time-small-height.html time-small-height-ref.html
+skip-if(Android) == time-small-width-height.html time-small-width-height-ref.html
+
+# content (text) should be left aligned
+skip-if(Android) == time-content-left-aligned.html time-content-left-aligned-ref.html
+
+# reset button should be right aligned
+skip-if(Android) fails-if(styloVsGecko) == time-reset-button-right-aligned.html time-reset-button-right-aligned-ref.html # bug 1372062
diff --git a/layout/reftests/forms/input/datetime/time-content-left-aligned-ref.html b/layout/reftests/forms/input/datetime/time-content-left-aligned-ref.html
new file mode 100644
index 000000000..ad8be9adc
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-content-left-aligned-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input type="time" style="width: 200px;">
+ <!-- div to cover the right area -->
+ <div style="display:block; position:absolute; background-color:black;
+ top:0px; left:40px; width:200px; height:100px;"></div>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-content-left-aligned.html b/layout/reftests/forms/input/datetime/time-content-left-aligned.html
new file mode 100644
index 000000000..aa910cddf
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-content-left-aligned.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input type="time" style="width: 50px;">
+ <!-- div to cover the right area -->
+ <div style="display:block; position:absolute; background-color:black;
+ top:0px; left:40px; width:200px; height:100px;"></div>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-reset-button-right-aligned-ref.html b/layout/reftests/forms/input/datetime/time-reset-button-right-aligned-ref.html
new file mode 100644
index 000000000..3d36f2068
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-reset-button-right-aligned-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input type="time" value="10:00" style="float: right; color: white;">
+ <!-- div to cover the left area -->
+ <div style="display:block; position:absolute; background-color:black;
+ top:0px; right:30px; width:500px; height:100px;"></div>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-reset-button-right-aligned.html b/layout/reftests/forms/input/datetime/time-reset-button-right-aligned.html
new file mode 100644
index 000000000..72d5cc140
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-reset-button-right-aligned.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <input type="time" value="10:00" style="width: 150px; float: right;
+ color: white;">
+ <!-- div to cover the left area -->
+ <div style="display:block; position:absolute; background-color:black;
+ top:0px; right:30px; width:500px; height:100px;"></div>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-height-ref.html b/layout/reftests/forms/input/datetime/time-small-height-ref.html
new file mode 100644
index 000000000..fcda93df9
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-height-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 200px;
+ height: 5px;
+ outline: 1px dotted black;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-height.html b/layout/reftests/forms/input/datetime/time-small-height.html
new file mode 100644
index 000000000..3044822fe
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-height.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 200px;
+ height: 5px;
+ outline: 1px dotted black;
+ color: white;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input type="time">
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-width-height-ref.html b/layout/reftests/forms/input/datetime/time-small-width-height-ref.html
new file mode 100644
index 000000000..0979243db
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-width-height-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 8px;
+ height: 8px;
+ outline: 1px dotted black;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-width-height.html b/layout/reftests/forms/input/datetime/time-small-width-height.html
new file mode 100644
index 000000000..a221b2819
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-width-height.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 8px;
+ height: 8px;
+ outline: 1px dotted black;
+ color: white;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input type="time">
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-width-ref.html b/layout/reftests/forms/input/datetime/time-small-width-ref.html
new file mode 100644
index 000000000..2379c7080
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-width-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 10px;
+ height: 1.5em;
+ outline: 1px dotted black;
+ background: white;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input>
+ </body>
+</html>
diff --git a/layout/reftests/forms/input/datetime/time-small-width.html b/layout/reftests/forms/input/datetime/time-small-width.html
new file mode 100644
index 000000000..f76f7fdfa
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/time-small-width.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+input {
+ width: 10px;
+ height: 1.5em;
+ outline: 1px dotted black;
+ color: white;
+ background: white;
+ /* Disable baseline alignment, so that our y-position isn't influenced by the
+ * choice of font inside of input: */
+ vertical-align: top;
+}
+ </style>
+ </head>
+ <body>
+ <input type="time">
+ </body>
+</html>
diff --git a/layout/reftests/forms/reftest.list b/layout/reftests/forms/reftest.list
index d45db276f..c7532077b 100644
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -1,4 +1,9 @@
fuzzy-if(skiaContent,1,10) HTTP(..) == text-control-baseline-1.html text-control-baseline-1-ref.html
+fuzzy-if(cocoaWidget,16,64) fuzzy-if(Android,52,64) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),104,224) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),57,400) == display-block-baselines-1.html display-block-baselines-1-ref.html # anti-aliasing issues
+== display-block-baselines-2.html display-block-baselines-2-ref.html
+== display-block-baselines-3.html display-block-baselines-3-ref.html
+== display-block-baselines-4.html display-block-baselines-4-ref.html
+fuzzy-if(Android,4,8) == display-block-baselines-5.html display-block-baselines-5-ref.html
# button element
include button/reftest.list
diff --git a/layout/reftests/scrolling/propagated-overflow-style-1-ref.html b/layout/reftests/scrolling/propagated-overflow-style-1-ref.html
new file mode 100644
index 000000000..7c2b1b315
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>
+ Reference case with body and html *independently* scrollable.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ body {
+ overflow: scroll;
+ }
+ </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-1a.html b/layout/reftests/scrolling/propagated-overflow-style-1a.html
new file mode 100644
index 000000000..b5115d36f
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-1a.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with body and html *independently* scrollable,
+ with body's "overflow" set dynamically.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.body.style.overflow = "scroll";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-1b.html b/layout/reftests/scrolling/propagated-overflow-style-1b.html
new file mode 100644
index 000000000..4608b87d6
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-1b.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with body and html *independently* scrollable,
+ with html's "overflow" set dynamically.
+ </title>
+ <style>
+ body {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.documentElement.style.overflow = "scroll";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-1c.html b/layout/reftests/scrolling/propagated-overflow-style-1c.html
new file mode 100644
index 000000000..11809915a
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-1c.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with body and html *independently* scrollable,
+ with both html & body's "overflow" set dynamically.
+ </title>
+ <script>
+ function doTest() {
+ document.documentElement.style.overflow = "scroll";
+ document.body.style.overflow = "scroll";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2-ref.html b/layout/reftests/scrolling/propagated-overflow-style-2-ref.html
new file mode 100644
index 000000000..20c3b8ae5
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>
+ Reference case with the root viewport scrollable, via styles on html node.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2a.html b/layout/reftests/scrolling/propagated-overflow-style-2a.html
new file mode 100644
index 000000000..250bedd6c
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2a.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with only one of [html,body] being scrollable,
+ after body's "overflow" is reset dynamically.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ body {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.body.style.overflow = "visible";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2b.html b/layout/reftests/scrolling/propagated-overflow-style-2b.html
new file mode 100644
index 000000000..c94ddedb2
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2b.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with only one of [html,body] being scrollable,
+ after html's "overflow" is reset dynamically.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ body {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.documentElement.style.overflow = "visible";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2c.html b/layout/reftests/scrolling/propagated-overflow-style-2c.html
new file mode 100644
index 000000000..0ceb1f21a
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2c.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with only one of [html,body] being scrollable,
+ with their "overflow" styles being dynamically swapped.
+ </title>
+ <style>
+ html {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.documentElement.style.overflow = "visible";
+ document.body.style.overflow = "scroll";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2d.html b/layout/reftests/scrolling/propagated-overflow-style-2d.html
new file mode 100644
index 000000000..3353a3374
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2d.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>
+ Testcase with only one of [html,body] being scrollable,
+ with their "overflow" styles being dynamically swapped.
+ </title>
+ <style>
+ body {
+ overflow: scroll;
+ }
+ </style>
+ <script>
+ function doTest() {
+ document.documentElement.style.overflow = "scroll";
+ document.body.style.overflow = "visible";
+ document.documentElement.removeAttribute("class");
+ }
+ window.addEventListener("MozReftestInvalidate", doTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/propagated-overflow-style-2e.html b/layout/reftests/scrolling/propagated-overflow-style-2e.html
new file mode 100644
index 000000000..f9105185b
--- /dev/null
+++ b/layout/reftests/scrolling/propagated-overflow-style-2e.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>
+ Testcase with the root viewport scrollable, via styles on body node.
+ </title>
+ <style>
+ body {
+ overflow: scroll;
+ }
+ </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list
index db1b81db6..43997ced7 100644
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -85,3 +85,13 @@ fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.htm
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
!= fractional-scroll-area-invalidation.html about:blank
+
+# Tests for "overflow" styles that may be propagated to the viewport:
+== propagated-overflow-style-1a.html propagated-overflow-style-1-ref.html
+== propagated-overflow-style-1b.html propagated-overflow-style-1-ref.html
+== propagated-overflow-style-1c.html propagated-overflow-style-1-ref.html
+== propagated-overflow-style-2a.html propagated-overflow-style-2-ref.html
+== propagated-overflow-style-2b.html propagated-overflow-style-2-ref.html
+== propagated-overflow-style-2c.html propagated-overflow-style-2-ref.html
+== propagated-overflow-style-2d.html propagated-overflow-style-2-ref.html
+== propagated-overflow-style-2e.html propagated-overflow-style-2-ref.html
diff --git a/layout/reftests/svg/radialGradient-fr-01.svg b/layout/reftests/svg/radialGradient-fr-01.svg
new file mode 100644
index 000000000..2f28d3aba
--- /dev/null
+++ b/layout/reftests/svg/radialGradient-fr-01.svg
@@ -0,0 +1,27 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>Test gradient fr attribute</title>
+ <defs>
+ <radialGradient id="grad1" fr="100%">
+ <stop offset="0%" stop-color="red" />
+ <stop offset="100%" stop-color="lime" />
+ </radialGradient>
+ <radialGradient id="grad2" xlink:href="#grad1"/>
+ <style>
+ circle {
+ stroke-width: 3px;
+ stroke: lime;
+ }
+ </style>
+ </defs>
+ <rect width="100%" height="100%" fill="lime"/>
+
+ <circle cx="100" cy="100" r="50" fill="url(#grad1)" />
+
+ <circle cx="300" cy="100" r="50" fill="url(#grad2)" />
+</svg>
+
diff --git a/layout/reftests/svg/radialGradient-fr-02-ref.svg b/layout/reftests/svg/radialGradient-fr-02-ref.svg
new file mode 100644
index 000000000..c256f72a2
--- /dev/null
+++ b/layout/reftests/svg/radialGradient-fr-02-ref.svg
@@ -0,0 +1,28 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>Test gradient fr attribute</title>
+ <defs>
+ <radialGradient id="grad1">
+ <stop offset="0%" stop-color="red" />
+ <stop offset="20%" stop-color="red" />
+ <stop offset="100%" stop-color="lime" />
+ </radialGradient>
+ <style>
+ .cover {
+ stroke-width: 3px;
+ stroke: lime;
+ fill: none;
+ image-rendering: optimizeSpeed;
+ }
+ </style>
+ </defs>
+ <rect width="100%" height="100%" fill="lime"/>
+
+ <circle cx="100" cy="100" r="50" fill="url(#grad1)" />
+ <circle class="cover" cx="100" cy="100" r="50" fill="none"/>
+</svg>
+
diff --git a/layout/reftests/svg/radialGradient-fr-02.svg b/layout/reftests/svg/radialGradient-fr-02.svg
new file mode 100644
index 000000000..1933203be
--- /dev/null
+++ b/layout/reftests/svg/radialGradient-fr-02.svg
@@ -0,0 +1,27 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title>Test gradient fr attribute</title>
+ <defs>
+ <radialGradient id="grad1" fr="10%">
+ <stop offset="0%" stop-color="red" />
+ <stop offset="100%" stop-color="lime" />
+ </radialGradient>
+ <style>
+ .cover {
+ stroke-width: 3px;
+ stroke: lime;
+ fill: none;
+ image-rendering: optimizeSpeed;
+ }
+ </style>
+ </defs>
+ <rect width="100%" height="100%" fill="lime"/>
+
+ <circle cx="100" cy="100" r="50" fill="url(#grad1)" />
+ <circle class="cover" cx="100" cy="100" r="50" />
+</svg>
+
diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list
index e596feae8..520adc9e6 100644
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -290,6 +290,8 @@ fuzzy-if(skiaContent,3,5) == pattern-scale-01c.svg pattern-scale-01-ref.svg
== radialGradient-basic-02.svg pass.svg
fuzzy-if(cocoaWidget,4,15982) fuzzy-if(winWidget,4,92) fuzzy-if(skiaContent,4,60) == radialGradient-basic-03.svg radialGradient-basic-03-ref.svg
== radialGradient-basic-04.svg pass.svg
+== radialGradient-fr-01.svg pass.svg
+fuzzy(1,3235) fuzzy-if(winWidget,1,6704) == radialGradient-fr-02.svg radialGradient-fr-02-ref.svg
fuzzy-if(skiaContent,1,3600) == rect-01.svg pass.svg
== rect-02.svg pass.svg
== rect-03.svg pass.svg
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001-ref.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001-ref.html
new file mode 100644
index 000000000..2473417b8
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<style>
+html, body { margin: 0; padding: 0; }
+
+.content {
+ margin-top: 100px;
+ width: 200px;
+ height: 200px;
+ background: blue;
+}
+</style>
+<body>
+ <div class="content"></div>
+</body>
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001.html
new file mode 100644
index 000000000..b6e2fdff0
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-align-items-center-nested-001.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Flexbox nested containers with align-items: center and flexible items</title>
+<link rel="match" href="flexbox-align-items-center-nested-001-ref.html">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#align-items-property">
+<style>
+html, body { margin: 0; padding: 0; }
+body {
+ height: 400px;
+ position: relative;
+}
+
+.container-0 {
+ display: flex;
+ position: absolute;
+ height: 100%;
+ flex-direction: column;
+}
+
+.container-1 {
+ flex: 1 0 auto;
+ display: flex;
+ align-items: center;
+}
+
+.container-2 {
+ height: 100%;
+ display: flex;
+ align-items: center;
+}
+
+.content {
+ width: 200px;
+ height: 200px;
+ background: blue;
+}
+</style>
+<body>
+ <div class="container-0">
+ <div class="container-1">
+ <div class="container-2">
+ <div class="content"></div>
+ </div>
+ </div>
+ </div>
+</body>
diff --git a/layout/reftests/w3c-css/submitted/flexbox/reftest.list b/layout/reftests/w3c-css/submitted/flexbox/reftest.list
index a623a0b59..fd8bfccc9 100644
--- a/layout/reftests/w3c-css/submitted/flexbox/reftest.list
+++ b/layout/reftests/w3c-css/submitted/flexbox/reftest.list
@@ -39,6 +39,8 @@ fuzzy-if(Android,158,32) == flexbox-align-self-vert-rtl-001.xhtml flexbox-align
== flexbox-align-self-vert-rtl-003.xhtml flexbox-align-self-vert-rtl-003-ref.xhtml
== flexbox-align-self-vert-rtl-004.xhtml flexbox-align-self-vert-rtl-004-ref.xhtml
+== flexbox-align-items-center-nested-001.html flexbox-align-items-center-nested-001-ref.html
+
# Tests for computing the baseline of a flex container
== flexbox-baseline-align-self-baseline-horiz-001.html flexbox-baseline-align-self-baseline-horiz-001-ref.html
== flexbox-baseline-align-self-baseline-vert-001.html flexbox-baseline-align-self-baseline-vert-001-ref.html
diff --git a/layout/reftests/xul/css-flex-1-ref.html b/layout/reftests/xul/css-flex-1-ref.html
new file mode 100644
index 000000000..a47eb8e9c
--- /dev/null
+++ b/layout/reftests/xul/css-flex-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body { margin: 0 }
+ div.ref {
+ border: 1px solid black;
+ box-sizing: border-box;
+ background: green;
+ height: 50px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div class="ref"></div>
+</body>
+</html>
diff --git a/layout/reftests/xul/css-flex-1.xul b/layout/reftests/xul/css-flex-1.xul
new file mode 100644
index 000000000..7955373dd
--- /dev/null
+++ b/layout/reftests/xul/css-flex-1.xul
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<head>
+<link rel="icon" href="/mozilla-central/static/hgicon.png" type="image/png" />
+<meta name="robots" content="index, nofollow"/>
+<link rel="stylesheet" href="/mozilla-central/static/style-gitweb.css" type="text/css" />
+
+<style type="text/css">
+div.feed {
+ float: right;
+}
+a img {
+ border-width: 0px;
+}
+div.log_link {
+ width: 80px;
+ background-color: white;
+}
+
+div.log_body {
+ padding-left: 96px;
+}
+</style>
+<script type="text/javascript" src="/mozilla-central/static/mercurial.js"></script>
+
+<link rel="stylesheet" href="/mozilla-central/highlightcss" type="text/css" />
+<title>mozilla-central: layout/reftests/xul/css-flex-1.xul@67bbef772796</title>
+<link rel="alternate" type="application/atom+xml"
+ href="/mozilla-central/atom-log" title="Atom feed for mozilla-central"/>
+<link rel="alternate" type="application/rss+xml"
+ href="/mozilla-central/rss-log" title="RSS feed for mozilla-central"/>
+</head>
+<body>
+
+<div class="page_header">
+<div class="logo"> <a href="https://developer.mozilla.org/en/docs/Mercurial"> <img src="/mozilla-central/static/moz-logo-bw-rgb.svg" alt="mercurial" /> </a> </div>
+<a href="/">Mercurial</a> &gt; <a href="/mozilla-central">mozilla-central</a> / file revision / layout/reftests/xul/css-flex-1.xul@67bbef772796
+</div>
+
+<div class="page_nav">
+<div>
+<a href="/mozilla-central/summary">summary</a> |
+<a href="/mozilla-central/shortlog">shortlog</a> |
+<a href="/mozilla-central/log">changelog</a> |
+<a href="/mozilla-central/pushloghtml">pushlog</a> |
+<a href="/mozilla-central/graph">graph</a> |
+<a href="/mozilla-central/tags">tags</a> |
+<a href="/mozilla-central/bookmarks">bookmarks</a> |
+<a href="/mozilla-central/branches">branches</a> |
+<a href="/mozilla-central/file/67bbef772796/layout/reftests/xul/">files</a> |
+<a href="/mozilla-central/rev/67bbef772796">changeset</a> |
+file |
+<a href="/mozilla-central/file/tip/layout/reftests/xul/css-flex-1.xul">latest</a> |
+<a href="/mozilla-central/log/67bbef772796/layout/reftests/xul/css-flex-1.xul">revisions</a> |
+<a href="/mozilla-central/annotate/67bbef772796/layout/reftests/xul/css-flex-1.xul">annotate</a> |
+<a href="/mozilla-central/diff/67bbef772796/layout/reftests/xul/css-flex-1.xul">diff</a> |
+<a href="/mozilla-central/comparison/67bbef772796/layout/reftests/xul/css-flex-1.xul">comparison</a> |
+<a href="/mozilla-central/raw-file/67bbef772796/layout/reftests/xul/css-flex-1.xul">raw</a> |
+<a href="/mozilla-central/help">help</a>
+</div>
+
+<div class="search">
+<form id="searchform" action="/mozilla-central/log">
+
+<input name="rev" type="text" value="" size="40" />
+<div id="hint">Find changesets by keywords (author, files, the commit message), revision
+number or hash, or <a href="/mozilla-central/help/revsets">revset expression</a>.</div>
+</form>
+</div>
+</div>
+
+<div class="title">layout/reftests/xul/css-flex-1.xul</div>
+
+<div class="title_text">
+<table cellspacing="0">
+<tr>
+ <td>author</td>
+ <td>&#68;&#97;&#110;&#105;&#101;&#108;&#32;&#72;&#111;&#108;&#98;&#101;&#114;&#116;&#32;&#60;&#100;&#104;&#111;&#108;&#98;&#101;&#114;&#116;&#64;&#99;&#115;&#46;&#115;&#116;&#97;&#110;&#102;&#111;&#114;&#100;&#46;&#101;&#100;&#117;&#62;</td>
+</tr>
+<tr>
+ <td></td>
+ <td class="date age">Wed, 08 Feb 2017 23:08:43 -0800</td>
+</tr>
+
+<tr>
+ <td>changeset 341731</td>
+ <td style="font-family:monospace"><a class="list" href="/mozilla-central/rev/67bbef772796">67bbef772796</a></td>
+</tr>
+
+
+<tr>
+ <td>permissions</td>
+ <td style="font-family:monospace">-rw-r--r--</td>
+</tr>
+</table>
+</div>
+
+<div class="page_path description"><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338053">Bug 1338053</a>: Make nsFlexContainerFrame::MarkIntrinsicISizesDirty() also call its parent class's method. r=emilio
+
+MozReview-Commit-ID: 72oIlunLcVq</div>
+
+<div class="page_body">
+<pre class="sourcelines stripes"
+ data-logurl="/mozilla-central/log/67bbef772796/layout/reftests/xul/css-flex-1.xul"
+ data-selectabletag="SPAN"
+ data-ishead="1">
+
+<a href="#l1"></a><span id="l1">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
+<a href="#l2"></a><span id="l2">&lt;window xmlns=&quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&quot;</span>
+<a href="#l3"></a><span id="l3"> class=&quot;reftest-wait&quot;</span>
+<a href="#l4"></a><span id="l4"> onload=&quot;tweak()&quot;&gt;</span>
+<a href="#l5"></a><span id="l5"> &lt;style xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;</span>
+<a href="#l6"></a><span id="l6"> &lt;![CDATA[</span>
+<a href="#l7"></a><span id="l7"> panelview {</span>
+<a href="#l8"></a><span id="l8"> border: 1px solid black;</span>
+<a href="#l9"></a><span id="l9"> background: green;</span>
+<a href="#l10"></a><span id="l10"> display: flex;</span>
+<a href="#l11"></a><span id="l11"> height: 50px;</span>
+<a href="#l12"></a><span id="l12"> }</span>
+<a href="#l13"></a><span id="l13"> ]]&gt;</span>
+<a href="#l14"></a><span id="l14"> &lt;/style&gt;</span>
+<a href="#l15"></a><span id="l15"> &lt;script&gt;</span>
+<a href="#l16"></a><span id="l16"> &lt;![CDATA[</span>
+<a href="#l17"></a><span id="l17"> function tweak() {</span>
+<a href="#l18"></a><span id="l18"> var tweakMe = document.getElementById(&quot;tweakMe&quot;);</span>
+<a href="#l19"></a><span id="l19"> tweakMe.style.width = &quot;100px&quot;;</span>
+<a href="#l20"></a><span id="l20"> document.documentElement.className = &quot;&quot;;</span>
+<a href="#l21"></a><span id="l21"> }</span>
+<a href="#l22"></a><span id="l22"> ]]&gt;</span>
+<a href="#l23"></a><span id="l23"> &lt;/script&gt;</span>
+<a href="#l24"></a><span id="l24"> &lt;hbox&gt;</span>
+<a href="#l25"></a><span id="l25"> &lt;panelview id=&quot;tweakMe&quot;&gt;&lt;/panelview&gt;</span>
+<a href="#l26"></a><span id="l26"> &lt;/hbox&gt;</span>
+<a href="#l27"></a><span id="l27">&lt;/window&gt;</span>
+</pre>
+</div>
+
+<script type="text/javascript" src="/mozilla-central/static/followlines.js"></script>
+
+<div class="page_footer">
+<div class="page_footer_text">mozilla-central</div>
+<div class="page_footer_text" style="padding-left: 10px">Deployed from <a href="https://hg.mozilla.org/hgcustom/version-control-tools/rev/bd13917afa61">bd13917afa61</a> at 2018-04-20T21:06:08Z.</div>
+<div class="rss_logo">
+<a href="/mozilla-central/rss-log">RSS</a>
+<a href="/mozilla-central/atom-log">Atom</a>
+</div>
+<br />
+
+</div>
+</body>
+</html>
+
diff --git a/layout/reftests/xul/reftest.list b/layout/reftests/xul/reftest.list
index da09b7c81..35b9f9025 100644
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -1,3 +1,5 @@
+== css-flex-1.xul css-flex-1-ref.html
+
== menuitem-key.xul menuitem-key-ref.xul
# these random-if(Android) are due to differences between Android Native & Xul, see bug 732569
random-if(Android) == menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul
diff --git a/layout/style/FontFaceSet.cpp b/layout/style/FontFaceSet.cpp
index 59626fba4..550a7d71a 100644
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -343,17 +343,7 @@ FontFaceSet::Load(JSContext* aCx,
}
}
- nsIGlobalObject* globalObject = GetParentObject();
- if (!globalObject) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- JS::Rooted<JSObject*> jsGlobal(aCx, globalObject->GetGlobalJSObject());
- GlobalObject global(aCx, jsGlobal);
-
- RefPtr<Promise> result = Promise::All(global, promises, aRv);
- return result.forget();
+ return Promise::All(aCx, promises, aRv);
}
bool
diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h
index febdd32c6..933ff6e7b 100644
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -742,6 +742,8 @@ CSS_KEY(button-focus, button_focus)
CSS_KEY(-moz-win-media-toolbox, _moz_win_media_toolbox)
CSS_KEY(-moz-win-communications-toolbox, _moz_win_communications_toolbox)
CSS_KEY(-moz-win-browsertabbar-toolbox, _moz_win_browsertabbar_toolbox)
+CSS_KEY(-moz-win-accentcolor, _moz_win_accentcolor)
+CSS_KEY(-moz-win-accentcolortext, _moz_win_accentcolortext)
CSS_KEY(-moz-win-mediatext, _moz_win_mediatext)
CSS_KEY(-moz-win-communicationstext, _moz_win_communicationstext)
CSS_KEY(-moz-win-glass, _moz_win_glass)
diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
index 1108ce5b5..b361cf0c2 100644
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -8918,6 +8918,10 @@ CSSParserImpl::ParseGridTrackSize(nsCSSValue& aValue,
return CSSParseResult::NotFound;
}
if (mToken.mIdent.LowerCaseEqualsLiteral("fit-content")) {
+ if (requireFixedSize) {
+ UngetToken();
+ return CSSParseResult::Error;
+ }
nsCSSValue::Array* func = aValue.InitFunction(eCSSKeyword_fit_content, 1);
if (ParseGridTrackBreadth(func->Item(1)) == CSSParseResult::Ok &&
func->Item(1).IsLengthPercentCalcUnit() &&
@@ -10400,7 +10404,8 @@ CSSParserImpl::ParseLinearGradient(nsCSSValue& aValue,
UngetToken();
// <angle> ,
- if (ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE, nullptr) &&
+ if (ParseSingleTokenVariant(cssGradient->mAngle,
+ VARIANT_ANGLE_OR_ZERO, nullptr) &&
!ExpectSymbol(',', true)) {
SkipUntil(')');
return false;
diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp
index ec28d06f8..f3a7f898d 100644
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1174,6 +1174,8 @@ const KTableEntry nsCSSProps::kColorKTable[] = {
{ eCSSKeyword__moz_oddtreerow, LookAndFeel::eColorID__moz_oddtreerow },
{ eCSSKeyword__moz_visitedhyperlinktext, NS_COLOR_MOZ_VISITEDHYPERLINKTEXT },
{ eCSSKeyword_currentcolor, NS_COLOR_CURRENTCOLOR },
+ { eCSSKeyword__moz_win_accentcolor, LookAndFeel::eColorID__moz_win_accentcolor },
+ { eCSSKeyword__moz_win_accentcolortext, LookAndFeel::eColorID__moz_win_accentcolortext },
{ eCSSKeyword__moz_win_mediatext, LookAndFeel::eColorID__moz_win_mediatext },
{ eCSSKeyword__moz_win_communicationstext, LookAndFeel::eColorID__moz_win_communicationstext },
{ eCSSKeyword__moz_nativehyperlinktext, LookAndFeel::eColorID__moz_nativehyperlinktext },
diff --git a/layout/style/nsCSSPseudoElements.h b/layout/style/nsCSSPseudoElements.h
index 657ef663e..eaf8d966b 100644
--- a/layout/style/nsCSSPseudoElements.h
+++ b/layout/style/nsCSSPseudoElements.h
@@ -111,8 +111,7 @@ private:
// which is a general gcc bug that we seem to have hit only on Android/x86.
#if defined(ANDROID) && defined(__i386__) && defined(__GNUC__) && \
!defined(__clang__)
-#if (MOZ_GCC_VERSION_AT_LEAST(4,8,0) && MOZ_GCC_VERSION_AT_MOST(4,8,4)) || \
- (MOZ_GCC_VERSION_AT_LEAST(4,9,0) && MOZ_GCC_VERSION_AT_MOST(4,9,2))
+#if (MOZ_GCC_VERSION_AT_LEAST(4,9,0) && MOZ_GCC_VERSION_AT_MOST(4,9,2))
__attribute__((noinline))
#endif
#endif
diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp
index 07a4ef57b..8760a330e 100644
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -1127,6 +1127,16 @@ InitSystemMetrics()
sSystemMetrics->AppendElement(nsGkAtoms::mac_yosemite_theme);
}
+ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorApplies, &metricResult);
+ if (NS_SUCCEEDED(rv) && metricResult) {
+ sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_applies);
+ }
+
+ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorIsDark, &metricResult);
+ if (NS_SUCCEEDED(rv) && metricResult) {
+ sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_is_dark);
+ }
+
rv = LookAndFeel::GetInt(LookAndFeel::eIntID_DWMCompositor, &metricResult);
if (NS_SUCCEEDED(rv) && metricResult) {
sSystemMetrics->AppendElement(nsGkAtoms::windows_compositor);
diff --git a/layout/style/nsLayoutStylesheetCache.cpp b/layout/style/nsLayoutStylesheetCache.cpp
index f8aea5541..e8c6d09d7 100644
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -23,19 +23,6 @@
#include "nsPrintfCString.h"
#include "nsXULAppAPI.h"
-// Includes for the crash report annotation in ErrorLoadingSheet.
-#ifdef MOZ_CRASHREPORTER
-#include "mozilla/Omnijar.h"
-#include "nsDirectoryService.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsExceptionHandler.h"
-#include "nsIChromeRegistry.h"
-#include "nsISimpleEnumerator.h"
-#include "nsISubstitutingProtocolHandler.h"
-#include "zlib.h"
-#include "nsZipArchive.h"
-#endif
-
using namespace mozilla;
using namespace mozilla::css;
@@ -463,280 +450,6 @@ nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile,
LoadSheet(uri, aSheet, aParsingMode, aFailureAction);
}
-#ifdef MOZ_CRASHREPORTER
-static inline nsresult
-ComputeCRC32(nsIFile* aFile, uint32_t* aResult)
-{
- PRFileDesc* fd;
- nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t crc = crc32(0, nullptr, 0);
-
- unsigned char buf[512];
- int32_t n;
- while ((n = PR_Read(fd, buf, sizeof(buf))) > 0) {
- crc = crc32(crc, buf, n);
- }
- PR_Close(fd);
-
- if (n < 0) {
- return NS_ERROR_FAILURE;
- }
-
- *aResult = crc;
- return NS_OK;
-}
-
-static void
-ListInterestingFiles(nsString& aAnnotation, nsIFile* aFile,
- const nsTArray<nsString>& aInterestingFilenames)
-{
- nsString filename;
- aFile->GetLeafName(filename);
- for (const nsString& interestingFilename : aInterestingFilenames) {
- if (interestingFilename == filename) {
- nsString path;
- aFile->GetPath(path);
- aAnnotation.AppendLiteral(" ");
- aAnnotation.Append(path);
- aAnnotation.AppendLiteral(" (");
- int64_t size;
- if (NS_SUCCEEDED(aFile->GetFileSize(&size))) {
- aAnnotation.AppendPrintf("%ld", size);
- } else {
- aAnnotation.AppendLiteral("???");
- }
- aAnnotation.AppendLiteral(" bytes, crc32 = ");
- uint32_t crc;
- nsresult rv = ComputeCRC32(aFile, &crc);
- if (NS_SUCCEEDED(rv)) {
- aAnnotation.AppendPrintf("0x%08x)\n", crc);
- } else {
- aAnnotation.AppendPrintf("error 0x%08x)\n", uint32_t(rv));
- }
- return;
- }
- }
-
- bool isDir = false;
- aFile->IsDirectory(&isDir);
-
- if (!isDir) {
- return;
- }
-
- nsCOMPtr<nsISimpleEnumerator> entries;
- if (NS_FAILED(aFile->GetDirectoryEntries(getter_AddRefs(entries)))) {
- aAnnotation.AppendLiteral(" (failed to enumerated directory)\n");
- return;
- }
-
- for (;;) {
- bool hasMore = false;
- if (NS_FAILED(entries->HasMoreElements(&hasMore))) {
- aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
- return;
- }
- if (!hasMore) {
- break;
- }
-
- nsCOMPtr<nsISupports> entry;
- if (NS_FAILED(entries->GetNext(getter_AddRefs(entry)))) {
- aAnnotation.AppendLiteral(" (failed during directory enumeration)\n");
- return;
- }
-
- nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
- if (file) {
- ListInterestingFiles(aAnnotation, file, aInterestingFilenames);
- }
- }
-}
-
-// Generate a crash report annotation to help debug issues with style
-// sheets failing to load (bug 1194856).
-static void
-AnnotateCrashReport(nsIURI* aURI)
-{
- nsAutoCString spec;
- nsAutoCString scheme;
- nsDependentCSubstring filename;
- if (aURI) {
- spec = aURI->GetSpecOrDefault();
- aURI->GetScheme(scheme);
- int32_t i = spec.RFindChar('/');
- if (i != -1) {
- filename.Rebind(spec, i + 1);
- }
- }
-
- nsString annotation;
-
- // The URL of the sheet that failed to load.
- annotation.AppendLiteral("Error loading sheet: ");
- annotation.Append(NS_ConvertUTF8toUTF16(spec).get());
- annotation.Append('\n');
-
- annotation.AppendLiteral("NS_ERROR_FILE_CORRUPTION reason: ");
- if (nsZipArchive::sFileCorruptedReason) {
- annotation.Append(NS_ConvertUTF8toUTF16(nsZipArchive::sFileCorruptedReason).get());
- annotation.Append('\n');
- } else {
- annotation.AppendLiteral("(none)\n");
- }
-
- // The jar: or file: URL that the sheet's resource: or chrome: URL
- // resolves to.
- if (scheme.EqualsLiteral("resource")) {
- annotation.AppendLiteral("Real location: ");
- nsCOMPtr<nsISubstitutingProtocolHandler> handler;
- nsCOMPtr<nsIIOService> io(do_GetIOService());
- if (io) {
- nsCOMPtr<nsIProtocolHandler> ph;
- io->GetProtocolHandler(scheme.get(), getter_AddRefs(ph));
- if (ph) {
- handler = do_QueryInterface(ph);
- }
- }
- if (!handler) {
- annotation.AppendLiteral("(ResolveURI failed)\n");
- } else {
- nsAutoCString resolvedSpec;
- handler->ResolveURI(aURI, resolvedSpec);
- annotation.Append(NS_ConvertUTF8toUTF16(resolvedSpec));
- annotation.Append('\n');
- }
- } else if (scheme.EqualsLiteral("chrome")) {
- annotation.AppendLiteral("Real location: ");
- nsCOMPtr<nsIChromeRegistry> reg =
- mozilla::services::GetChromeRegistryService();
- if (!reg) {
- annotation.AppendLiteral("(no chrome registry)\n");
- } else {
- nsCOMPtr<nsIURI> resolvedURI;
- reg->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
- if (!resolvedURI) {
- annotation.AppendLiteral("(ConvertChromeURL failed)\n");
- } else {
- annotation.Append(
- NS_ConvertUTF8toUTF16(resolvedURI->GetSpecOrDefault()));
- annotation.Append('\n');
- }
- }
- }
-
- nsTArray<nsString> interestingFiles;
- interestingFiles.AppendElement(NS_LITERAL_STRING("chrome.manifest"));
- interestingFiles.AppendElement(NS_LITERAL_STRING("omni.ja"));
- interestingFiles.AppendElement(NS_ConvertUTF8toUTF16(filename));
-
- annotation.AppendLiteral("GRE directory: ");
- nsCOMPtr<nsIFile> file;
- nsDirectoryService::gService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
- getter_AddRefs(file));
- if (file) {
- // The Firefox installation directory.
- nsString path;
- file->GetPath(path);
- annotation.Append(path);
- annotation.Append('\n');
-
- // List interesting files -- any chrome.manifest or omni.ja file or any file
- // whose name is the sheet's filename -- under the Firefox installation
- // directory.
- annotation.AppendLiteral("Interesting files in the GRE directory:\n");
- ListInterestingFiles(annotation, file, interestingFiles);
-
- // If the Firefox installation directory has a chrome.manifest file, let's
- // see what's in it.
- file->Append(NS_LITERAL_STRING("chrome.manifest"));
- bool exists = false;
- file->Exists(&exists);
- if (exists) {
- annotation.AppendLiteral("Contents of chrome.manifest:\n[[[\n");
- PRFileDesc* fd;
- if (NS_SUCCEEDED(file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))) {
- nsCString contents;
- char buf[512];
- int32_t n;
- while ((n = PR_Read(fd, buf, sizeof(buf))) > 0) {
- contents.Append(buf, n);
- }
- if (n < 0) {
- annotation.AppendLiteral(" (error while reading)\n");
- } else {
- annotation.Append(NS_ConvertUTF8toUTF16(contents));
- }
- PR_Close(fd);
- }
- annotation.AppendLiteral("]]]\n");
- }
- } else {
- annotation.AppendLiteral("(none)\n");
- }
-
- // The jar: or file: URL prefix that chrome: and resource: URLs get translated
- // to.
- annotation.AppendLiteral("GRE omnijar URI string: ");
- nsCString uri;
- nsresult rv = Omnijar::GetURIString(Omnijar::GRE, uri);
- if (NS_FAILED(rv)) {
- annotation.AppendLiteral("(failed)\n");
- } else {
- annotation.Append(NS_ConvertUTF8toUTF16(uri));
- annotation.Append('\n');
- }
-
- RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
- if (zip) {
- // List interesting files in the GRE omnijar.
- annotation.AppendLiteral("Interesting files in the GRE omnijar:\n");
- nsZipFind* find;
- rv = zip->FindInit(nullptr, &find);
- if (NS_FAILED(rv)) {
- annotation.AppendPrintf(" (FindInit failed with 0x%08x)\n", rv);
- } else if (!find) {
- annotation.AppendLiteral(" (FindInit returned null)\n");
- } else {
- const char* result;
- uint16_t len;
- while (NS_SUCCEEDED(find->FindNext(&result, &len))) {
- nsCString itemPathname;
- nsString itemFilename;
- itemPathname.Append(result, len);
- int32_t i = itemPathname.RFindChar('/');
- if (i != -1) {
- itemFilename = NS_ConvertUTF8toUTF16(Substring(itemPathname, i + 1));
- }
- for (const nsString& interestingFile : interestingFiles) {
- if (interestingFile == itemFilename) {
- annotation.AppendLiteral(" ");
- annotation.Append(NS_ConvertUTF8toUTF16(itemPathname));
- nsZipItem* item = zip->GetItem(itemPathname.get());
- if (!item) {
- annotation.AppendLiteral(" (GetItem failed)\n");
- } else {
- annotation.AppendPrintf(" (%d bytes, crc32 = 0x%08x)\n",
- item->RealSize(),
- item->CRC32());
- }
- break;
- }
- }
- }
- delete find;
- }
- } else {
- annotation.AppendLiteral("No GRE omnijar\n");
- }
-
- CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("SheetLoadFailure"),
- NS_ConvertUTF16toUTF8(annotation));
-}
-#endif
-
static void
ErrorLoadingSheet(nsIURI* aURI, const char* aMsg, FailureAction aFailureAction)
{
@@ -751,9 +464,6 @@ ErrorLoadingSheet(nsIURI* aURI, const char* aMsg, FailureAction aFailureAction)
}
}
-#ifdef MOZ_CRASHREPORTER
- AnnotateCrashReport(aURI);
-#endif
NS_RUNTIMEABORT(errorMessage.get());
}
@@ -780,9 +490,6 @@ nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
}
}
-#ifdef MOZ_CRASHREPORTER
- nsZipArchive::sFileCorruptedReason = nullptr;
-#endif
nsresult rv = loader->LoadSheetSync(aURI, aParsingMode, true, aSheet);
if (NS_FAILED(rv)) {
ErrorLoadingSheet(aURI,
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
index c07a4123e..5a54d5455 100644
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -70,8 +70,6 @@ struct OperatingSystemVersionInfo {
// Os version identities used in the -moz-os-version media query.
const OperatingSystemVersionInfo osVersionStrings[] = {
- { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" },
- { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" },
{ LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
{ LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
{ LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" }
@@ -716,6 +714,22 @@ nsMediaFeatures::features[] = {
GetSystemMetric
},
{
+ &nsGkAtoms::_moz_windows_accent_color_applies,
+ nsMediaFeature::eMinMaxNotAllowed,
+ nsMediaFeature::eBoolInteger,
+ nsMediaFeature::eNoRequirements,
+ { &nsGkAtoms::windows_accent_color_applies },
+ GetSystemMetric
+ },
+ {
+ &nsGkAtoms::_moz_windows_accent_color_is_dark,
+ nsMediaFeature::eMinMaxNotAllowed,
+ nsMediaFeature::eBoolInteger,
+ nsMediaFeature::eNoRequirements,
+ { &nsGkAtoms::windows_accent_color_is_dark },
+ GetSystemMetric
+ },
+ {
&nsGkAtoms::_moz_windows_compositor,
nsMediaFeature::eMinMaxNotAllowed,
nsMediaFeature::eBoolInteger,
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
index b22002d87..fa29fe0f1 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -4686,7 +4686,8 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
if (font->mSize != 0) {
lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
} else {
- lh = minimumFontSize;
+ // Never shrink line heights as a result of minFontSize
+ lh = std::max(lh, minimumFontSize);
}
}
text->mLineHeight.SetCoordValue(lh);
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
index 2f12d6201..553239e0e 100644
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1629,23 +1629,11 @@ nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
if (aOldStyleVisibility) {
bool isVertical = WritingMode(aOldStyleVisibility).IsVertical();
if (isVertical ? widthChanged : heightChanged) {
- // Block-size changes can affect descendant intrinsic sizes due to
- // replaced elements with percentage bsizes in descendants which
- // also have percentage bsizes. This is handled via
- // nsChangeHint_UpdateComputedBSize which clears intrinsic sizes
- // for frames that have such replaced elements.
- hint |= nsChangeHint_NeedReflow |
- nsChangeHint_UpdateComputedBSize |
- nsChangeHint_ReflowChangesSizeOrPosition;
+ hint |= nsChangeHint_ReflowHintsForBSizeChange;
}
if (isVertical ? heightChanged : widthChanged) {
- // None of our inline-size differences can affect descendant
- // intrinsic sizes and none of them need to force children to
- // reflow.
- hint |= nsChangeHint_AllReflowHints &
- ~(nsChangeHint_ClearDescendantIntrinsics |
- nsChangeHint_NeedDirtyReflow);
+ hint |= nsChangeHint_ReflowHintsForISizeChange;
}
} else {
if (widthChanged || heightChanged) {
@@ -3258,8 +3246,6 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
|| mDisplay != aNewData.mDisplay
|| mContain != aNewData.mContain
|| (mFloat == StyleFloat::None) != (aNewData.mFloat == StyleFloat::None)
- || mOverflowX != aNewData.mOverflowX
- || mOverflowY != aNewData.mOverflowY
|| mScrollBehavior != aNewData.mScrollBehavior
|| mScrollSnapTypeX != aNewData.mScrollSnapTypeX
|| mScrollSnapTypeY != aNewData.mScrollSnapTypeY
@@ -3271,6 +3257,11 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
hint |= nsChangeHint_ReconstructFrame;
}
+ if (mOverflowX != aNewData.mOverflowX
+ || mOverflowY != aNewData.mOverflowY) {
+ hint |= nsChangeHint_CSSOverflowChange;
+ }
+
/* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
* mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
* changed, nsChangeHint_NeutralChange is not sufficient to enter
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index ca5d03056..05a6be91e 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1197,11 +1197,14 @@ private:
nsCSSShadowItem mArray[1]; // This MUST be the last item
};
-// Border widths are rounded to the nearest-below integer number of pixels,
-// but values between zero and one device pixels are always rounded up to
-// one device pixel.
+// Border widths are rounded to the nearest integer number of pixels, but values
+// between zero and one device pixels are always rounded up to one device pixel.
#define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
- ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
+ ((l) == 0) ? 0 : std::max((tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp))
+// Caret widths are rounded to the nearest-below integer number of pixels, but values
+// between zero and one device pixels are always rounded up to one device pixel.
+#define NS_ROUND_CARET_TO_PIXELS(l,tpp) \
+ ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
// Outline offset is rounded to the nearest integer number of pixels, but values
// between zero and one device pixels are always rounded up to one device pixel.
// Note that the offset can be negative.
diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css
index f045540b1..e7566e183 100644
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -1135,3 +1135,8 @@ input[type="number"] > div > div > div:hover {
/* give some indication of hover state for the up/down buttons */
background-color: lightblue;
}
+
+input[type="date"],
+input[type="time"] {
+ overflow: hidden !important;
+}
diff --git a/layout/style/res/html.css b/layout/style/res/html.css
index a779461de..bc3f08210 100644
--- a/layout/style/res/html.css
+++ b/layout/style/res/html.css
@@ -774,6 +774,11 @@ input[type="time"] > xul|datetimebox {
-moz-binding: url("chrome://global/content/bindings/datetimebox.xml#time-input");
}
+input[type="date"] > xul|datetimebox {
+ display: flex;
+ -moz-binding: url("chrome://global/content/bindings/datetimebox.xml#date-input");
+}
+
/* details & summary */
/* Need to revert Bug 1259889 Part 2 when removing details preference. */
@supports -moz-bool-pref("dom.details_element.enabled") {
diff --git a/layout/style/test/chrome/bug418986-2.js b/layout/style/test/chrome/bug418986-2.js
index 4336f4abd..b083f48ee 100644
--- a/layout/style/test/chrome/bug418986-2.js
+++ b/layout/style/test/chrome/bug418986-2.js
@@ -53,8 +53,6 @@ var suppressed_toggles = [
// Possible values for '-moz-os-version'
var windows_versions = [
- "windows-xp",
- "windows-vista",
"windows-win7",
"windows-win8",
"windows-win10",
diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini
index 406c6f901..8182691ca 100644
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -295,6 +295,7 @@ skip-if = toolkit == 'android'
[test_variables.html]
support-files = support/external-variable-url.css
[test_video_object_fit.html]
+[test_viewport_scrollbar_causing_reflow.html]
[test_viewport_units.html]
[test_visited_image_loading.html]
skip-if = toolkit == 'android' #TIMED_OUT
diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js
index 9c69e7d10..62d413d98 100644
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -132,6 +132,9 @@ var validGradientAndElementValues = [
"linear-gradient(to right bottom, red, 50%, green 50%, 50%, blue)",
"linear-gradient(to right bottom, red, 0%, green 50%, 100%, blue)",
+ /* Unitless 0 is valid as an <angle> */
+ "linear-gradient(0, red, blue)",
+
"-moz-linear-gradient(red, blue)",
"-moz-linear-gradient(red, yellow, blue)",
"-moz-linear-gradient(red 1px, yellow 20%, blue 24em, green)",
@@ -388,10 +391,8 @@ var invalidGradientAndElementValues = [
"-moz-linear-gradient(10 10px -45deg, red, blue) repeat",
"-moz-linear-gradient(10px 10 -45deg, red, blue) repeat",
"linear-gradient(red -99, yellow, green, blue 120%)",
- /* Unitless 0 is invalid as an <angle> */
- "-moz-linear-gradient(top left 0, red, blue)",
- "-moz-linear-gradient(5px 5px 0, red, blue)",
- "linear-gradient(0, red, blue)",
+ /* Unitless nonzero numbers are valid as an <angle> */
+ "linear-gradient(30, red, blue)",
/* Invalid color, calc() or -moz-image-rect() function */
"linear-gradient(red, rgb(0, rubbish, 0) 50%, red)",
"linear-gradient(red, red calc(50% + rubbish), red)",
@@ -6270,6 +6271,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"repeat(auto-fill,minmax(1%,auto))",
"repeat(auto-fill,minmax(1em,min-content)) minmax(min-content,0)",
"repeat(auto-fill,minmax(max-content,1mm))",
+ "repeat(2, fit-content(1px))",
"fit-content(1px) 1fr",
"[a] fit-content(calc(1px - 99%)) [b]",
"[a] fit-content(10%) [b c] fit-content(1em)",
@@ -6314,6 +6316,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"repeat(1, repeat(1, 20px))",
"repeat(auto-fill, auto)",
"repeat(auto-fit,auto)",
+ "repeat(auto-fill, fit-content(1px))",
+ "repeat(auto-fit, fit-content(1px))",
"repeat(auto-fit,[])",
"repeat(auto-fill, 0) repeat(auto-fit, 0) ",
"repeat(auto-fit, 0) repeat(auto-fill, 0) ",
@@ -6335,6 +6339,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"fit-content(-1px)",
"fit-content(auto)",
"fit-content(min-content)",
+ "fit-content(1px) repeat(auto-fit, 1px)",
+ "fit-content(1px) repeat(auto-fill, 1px)",
],
unbalanced_values: [
"(foo] 40px",
diff --git a/layout/style/test/test_dynamic_change_causing_reflow.html b/layout/style/test/test_dynamic_change_causing_reflow.html
index a941191f6..a5bb3045c 100644
--- a/layout/style/test/test_dynamic_change_causing_reflow.html
+++ b/layout/style/test/test_dynamic_change_causing_reflow.html
@@ -95,6 +95,90 @@ const gTestcases = [
expectReflow: true,
},
+ // * Changing 'overflow' on <body> should cause reflow,
+ // but not frame reconstruction
+ {
+ elem: document.body,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: scroll",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: scroll",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: hidden",
+ afterStyle: "overflow: visible",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: auto",
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.body,
+ beforeStyle: "overflow: visible",
+ afterStyle: "overflow: hidden",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+
+ // * Changing 'overflow' on <html> should cause reflow,
+ // but not frame reconstruction
+ {
+ elem: document.documentElement,
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+ {
+ elem: document.documentElement,
+ beforeStyle: "overflow: visible",
+ afterStyle: "overflow: auto",
+ expectConstruction: false,
+ expectReflow: true,
+ },
+
+ // * Setting 'overflow' on arbitrary node should cause reflow as well as
+ // frame reconstruction
+ {
+ /* beforeStyle: implicitly 'overflow:visible' */
+ afterStyle: "overflow: auto",
+ expectConstruction: true,
+ expectReflow: true,
+ },
+ {
+ beforeStyle: "overflow: auto",
+ afterStyle: "overflow: visible",
+ expectConstruction: true,
+ expectReflow: true,
+ },
+
// * Changing 'display' should cause frame construction and reflow.
{
beforeStyle: "display: inline",
@@ -135,23 +219,34 @@ function runOneTest(aTestcase)
return;
}
+ // Figure out which element we'll be tweaking (defaulting to gElem)
+ let elem = aTestcase.elem ?
+ aTestcase.elem : gElem;
+
+ // Verify that 'style' attribute is unset (avoid causing ourselves trouble):
+ if (elem.hasAttribute("style")) {
+ ok(false,
+ "test element has 'style' attribute already set! We're going to stomp " +
+ "on whatever's there when we clean up...");
+ }
+
// Set the "before" style, and compose the first part of the message
// to be used in our "is"/"isnot" invocations:
let msgPrefix = "Changing style ";
if (aTestcase.beforeStyle) {
- gElem.setAttribute("style", aTestcase.beforeStyle);
+ elem.setAttribute("style", aTestcase.beforeStyle);
msgPrefix += "from '" + aTestcase.beforeStyle + "' ";
}
- msgPrefix += "to '" + aTestcase.afterStyle + "' ";
+ msgPrefix += "on " + elem.nodeName + " ";
// Establish initial counts:
- let unusedVal = gElem.offsetHeight; // flush layout
+ let unusedVal = elem.offsetHeight; // flush layout
let origFramesConstructed = gUtils.framesConstructed;
let origFramesReflowed = gUtils.framesReflowed;
// Make the change and flush:
- gElem.setAttribute("style", aTestcase.afterStyle);
- unusedVal = gElem.offsetHeight; // flush layout
+ elem.setAttribute("style", aTestcase.afterStyle);
+ unusedVal = elem.offsetHeight; // flush layout
// Make our is/isnot assertions about whether things should have changed:
checkFinalCount(gUtils.framesConstructed, origFramesConstructed,
@@ -162,7 +257,7 @@ function runOneTest(aTestcase)
"reflow");
// Clean up!
- gElem.removeAttribute("style");
+ elem.removeAttribute("style");
}
gTestcases.forEach(runOneTest);
diff --git a/layout/style/test/test_media_queries.html b/layout/style/test/test_media_queries.html
index 1edac15ae..d503fad0b 100644
--- a/layout/style/test/test_media_queries.html
+++ b/layout/style/test/test_media_queries.html
@@ -628,6 +628,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme");
expression_should_be_parseable("-moz-mac-graphite-theme");
expression_should_be_parseable("-moz-mac-yosemite-theme");
+ expression_should_be_parseable("-moz-windows-accent-color-applies");
expression_should_be_parseable("-moz-windows-compositor");
expression_should_be_parseable("-moz-windows-classic");
expression_should_be_parseable("-moz-windows-glass");
@@ -643,6 +644,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme: 0");
expression_should_be_parseable("-moz-mac-graphite-theme: 0");
expression_should_be_parseable("-moz-mac-yosemite-theme: 0");
+ expression_should_be_parseable("-moz-windows-accent-color-applies: 0");
expression_should_be_parseable("-moz-windows-compositor: 0");
expression_should_be_parseable("-moz-windows-classic: 0");
expression_should_be_parseable("-moz-windows-glass: 0");
@@ -658,6 +660,7 @@ function run() {
expression_should_be_parseable("-moz-windows-default-theme: 1");
expression_should_be_parseable("-moz-mac-graphite-theme: 1");
expression_should_be_parseable("-moz-mac-yosemite-theme: 1");
+ expression_should_be_parseable("-moz-windows-accent-color-applies: 1");
expression_should_be_parseable("-moz-windows-compositor: 1");
expression_should_be_parseable("-moz-windows-classic: 1");
expression_should_be_parseable("-moz-windows-glass: 1");
@@ -673,6 +676,7 @@ function run() {
expression_should_not_be_parseable("-moz-windows-default-theme: -1");
expression_should_not_be_parseable("-moz-mac-graphite-theme: -1");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: -1");
+ expression_should_not_be_parseable("-moz-windows-accent-color-applies: -1");
expression_should_not_be_parseable("-moz-windows-compositor: -1");
expression_should_not_be_parseable("-moz-windows-classic: -1");
expression_should_not_be_parseable("-moz-windows-glass: -1");
@@ -688,6 +692,7 @@ function run() {
expression_should_not_be_parseable("-moz-windows-default-theme: true");
expression_should_not_be_parseable("-moz-mac-graphite-theme: true");
expression_should_not_be_parseable("-moz-mac-yosemite-theme: true");
+ expression_should_not_be_parseable("-moz-windows-accent-color-applies: true");
expression_should_not_be_parseable("-moz-windows-compositor: true");
expression_should_not_be_parseable("-moz-windows-classic: true");
expression_should_not_be_parseable("-moz-windows-glass: true");
@@ -708,8 +713,6 @@ function run() {
expression_should_not_be_parseable("-moz-windows-theme: ");
// os version media queries (currently windows only)
- expression_should_be_parseable("-moz-os-version: windows-xp");
- expression_should_be_parseable("-moz-os-version: windows-vista");
expression_should_be_parseable("-moz-os-version: windows-win7");
expression_should_be_parseable("-moz-os-version: windows-win8");
expression_should_be_parseable("-moz-os-version: windows-win10");
diff --git a/layout/style/test/test_viewport_scrollbar_causing_reflow.html b/layout/style/test/test_viewport_scrollbar_causing_reflow.html
new file mode 100644
index 000000000..dfd7ec450
--- /dev/null
+++ b/layout/style/test/test_viewport_scrollbar_causing_reflow.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1367568
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1367568</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1367568</a>
+<div id="content">
+ <!-- Some fixed-width divs that we shouldn't have to reflow when the viewport
+ changes: -->
+ <div style="width: 100px">
+ fixed-width
+ <div>(child)</div>
+ </div>
+ <div style="position: absolute; width: 150px">
+ abs-fixed-width
+ <div>(child)</div>
+ </div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+"use strict";
+
+/** Test for Bug 1367568 **/
+
+/**
+ * This test verifies that "overflow" changes on the <body> don't cause
+ * an unnecessarily large amount of reflow.
+ */
+
+// Vars used in setStyleAndMeasure that we really only have to look up once:
+const gUtils = SpecialPowers.getDOMWindowUtils(window);
+
+function setStyleAndMeasure(initialStyle, finalStyle) {
+ is(document.body.style.length, 0,
+ "Bug in test - body should start with empty style");
+ let unusedVal = document.body.offsetHeight; // flush layout
+ let constructCount = gUtils.framesConstructed;
+
+ document.body.style = initialStyle;
+ unusedVal = document.body.offsetHeight; // flush layout
+ let reflowCountBeforeTweak = gUtils.framesReflowed;
+
+ document.body.style = finalStyle;
+ unusedVal = document.body.offsetHeight; // flush layout
+ let reflowCountAfterTweak = gUtils.framesReflowed;
+
+ // Clean up:
+ document.body.style = "";
+
+ is(gUtils.framesConstructed, constructCount,
+ "Style tweak shouldn't have triggered frame construction");
+
+ // ...and return the delta:
+ return reflowCountAfterTweak - reflowCountBeforeTweak;
+}
+
+function main() {
+ // First, we sanity-check that our measurement make sense -- if we leave
+ // styles unchanged, we should measure no frames being reflowed:
+ let count = setStyleAndMeasure("width: 50px; height: 80px",
+ "width: 50px; height: 80px");
+ is(count, 0,
+ "Shouldn't reflow anything when we leave 'width' & 'height' unchanged");
+
+ // Now: see how many frames are reflowed when the "width" & "height" change.
+ // We'll use this as the reference when measuring reflow counts for various
+ // changes to "overflow" below.
+ count = setStyleAndMeasure("width: 50px; height: 80px",
+ "width: 90px; height: 60px");
+ ok(count > 0,
+ "Should reflow some frames when 'width' & 'height' change");
+
+ // Expected maximum number of frames reflowed for "overflow" changes
+ // (+2 is to allow for reflowing scrollbars themselves):
+ const expectedMax = count + 2;
+
+ // Shared ending for messages in all ok() checks below:
+ const messageSuffix =
+ " shouldn't be greater than count for tweaking width/height on body (" +
+ expectedMax + ")";
+
+ // OK, here is where the relevant tests actually begin!!
+ // See how many frames we reflow for various tweaks to "overflow" on
+ // the body -- we expect the count to be no larger than |expectedMax|.
+ count = setStyleAndMeasure("", "overflow: scroll");
+ ok(count <= expectedMax,
+ "Reflow count when setting 'overflow: scroll' on body (" + count + ")" +
+ messageSuffix);
+
+ count = setStyleAndMeasure("", "overflow: hidden");
+ ok(count <= expectedMax,
+ "Reflow count when setting 'overflow: hidden' on body (" + count + ")" +
+ messageSuffix);
+
+ // Test removal of "overflow: scroll":
+ count = setStyleAndMeasure("overflow: scroll", "");
+ ok(count <= expectedMax,
+ "Reflow count when removing 'overflow: scroll' from body (" + count + ")" +
+ messageSuffix);
+
+ count = setStyleAndMeasure("overflow: hidden", "");
+ ok(count <= expectedMax,
+ "Reflow count when removing 'overflow: hidden' from body (" + count + ")" +
+ messageSuffix);
+
+ // Test change between two non-'visible' overflow values:
+ count = setStyleAndMeasure("overflow: scroll", "overflow: hidden");
+ ok(count <= expectedMax,
+ "Reflow count when changing 'overflow' on body (" + count + ")" +
+ messageSuffix);
+}
+
+main();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp
index e68126068..e5a03333f 100644
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -5111,8 +5111,8 @@ SVGTextFrame::DoGlyphPositioning()
float actualTextLength =
static_cast<float>(presContext->AppUnitsToGfxUnits(frameLength) * factor);
- RefPtr<SVGAnimatedEnumeration> lengthAdjustEnum = element->LengthAdjust();
- uint16_t lengthAdjust = lengthAdjustEnum->AnimVal();
+ uint16_t lengthAdjust =
+ element->EnumAttributes()[SVGTextContentElement::LENGTHADJUST].GetAnimValue();
switch (lengthAdjust) {
case SVG_LENGTHADJUST_SPACINGANDGLYPHS:
// Scale the glyphs and their positions.
diff --git a/layout/svg/nsSVGGradientFrame.cpp b/layout/svg/nsSVGGradientFrame.cpp
index 217ab8c4a..2d7684f5a 100644
--- a/layout/svg/nsSVGGradientFrame.cpp
+++ b/layout/svg/nsSVGGradientFrame.cpp
@@ -623,7 +623,7 @@ nsSVGRadialGradientFrame::GradientVectorLengthIsZero()
already_AddRefed<gfxPattern>
nsSVGRadialGradientFrame::CreateGradient()
{
- float cx, cy, r, fx, fy;
+ float cx, cy, r, fx, fy, fr;
cx = GetLengthValue(dom::SVGRadialGradientElement::ATTR_CX);
cy = GetLengthValue(dom::SVGRadialGradientElement::ATTR_CY);
@@ -631,6 +631,7 @@ nsSVGRadialGradientFrame::CreateGradient()
// If fx or fy are not set, use cx/cy instead
fx = GetLengthValue(dom::SVGRadialGradientElement::ATTR_FX, cx);
fy = GetLengthValue(dom::SVGRadialGradientElement::ATTR_FY, cy);
+ fr = GetLengthValue(dom::SVGRadialGradientElement::ATTR_FR);
if (fx != cx || fy != cy) {
// The focal point (fFx and fFy) must be clamped to be *inside* - not on -
@@ -651,7 +652,7 @@ nsSVGRadialGradientFrame::CreateGradient()
}
}
- RefPtr<gfxPattern> pattern = new gfxPattern(fx, fy, 0, cx, cy, r);
+ RefPtr<gfxPattern> pattern = new gfxPattern(fx, fy, fr, cx, cy, r);
return pattern.forget();
}
diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp
index ff74d5baf..344ebf645 100644
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1127,8 +1127,7 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
if (clipPathFrame && isOK) {
SVGClipPathElement *clipContent =
static_cast<SVGClipPathElement*>(clipPathFrame->GetContent());
- RefPtr<SVGAnimatedEnumeration> units = clipContent->ClipPathUnits();
- if (units->AnimVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (clipContent->IsUnitsObjectBoundingBox()) {
matrix.Translate(gfxPoint(x, y));
matrix.Scale(width, height);
} else if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
diff --git a/layout/tools/recording/recording-cmdline.js b/layout/tools/recording/recording-cmdline.js
index e043aa29c..0f127bbd5 100644
--- a/layout/tools/recording/recording-cmdline.js
+++ b/layout/tools/recording/recording-cmdline.js
@@ -67,8 +67,8 @@ RecordingCmdLineHandler.prototype =
cmdLine.preventDefault = true;
},
- helpInfo : " --recording <file> Record drawing for a given URL.\n" +
- " --recording-output <file> Specify destination file for a drawing recording.\n"
+ helpInfo : " --recording <file> Record drawing for a given URL.\n" +
+ " --recording-output <file> Specify destination file for a drawing recording.\n"
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RecordingCmdLineHandler]);