From 317b96a1beeeb64eae41b195738e507a6e75193d Mon Sep 17 00:00:00 2001 From: Moonchild Date: Fri, 16 Oct 2020 10:19:19 +0000 Subject: [PATCH 1/7] Issue #1643 - Follow-up: Ensure we properly clear our pointers when the Presentation of a document is destroyed. --- dom/base/ResizeObserverController.cpp | 22 +++++++++++++--------- dom/base/ResizeObserverController.h | 5 +++++ dom/base/nsDocument.cpp | 6 ++++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/dom/base/ResizeObserverController.cpp b/dom/base/ResizeObserverController.cpp index acc401a5e2..d2162bb62e 100644 --- a/dom/base/ResizeObserverController.cpp +++ b/dom/base/ResizeObserverController.cpp @@ -15,7 +15,7 @@ namespace dom { void ResizeObserverNotificationHelper::WillRefresh(TimeStamp aTime) { - MOZ_ASSERT(mOwner, "Why is mOwner already dead when this RefreshObserver is still registered?"); + MOZ_DIAGNOSTIC_ASSERT(mOwner, "RefreshObserver should have been de-registered on time, but isn't."); if (mOwner) { mOwner->Notify(); } @@ -69,10 +69,8 @@ ResizeObserverNotificationHelper::Unregister() } nsRefreshDriver* refreshDriver = GetRefreshDriver(); - if (!refreshDriver) { - // We can't access RefreshDriver now. Just abort the Unregister(). - return; - } + MOZ_RELEASE_ASSERT(refreshDriver, + "We should not leave a dangling reference to the observer around"); refreshDriver->RemoveRefreshObserver(this, Flush_Display); mRegistered = false; @@ -81,9 +79,8 @@ ResizeObserverNotificationHelper::Unregister() void ResizeObserverNotificationHelper::Disconnect() { - Unregister(); - // Our owner is dying. Clear our pointer to it, in case we outlive it. - mOwner = nullptr; + MOZ_RELEASE_ASSERT(!mRegistered, "How can we die when registered?"); + MOZ_RELEASE_ASSERT(!mOwner, "Forgot to clear weak pointer?"); } ResizeObserverNotificationHelper::~ResizeObserverNotificationHelper() @@ -111,6 +108,10 @@ ResizeObserverController::AddResizeObserver(ResizeObserver* aObserver) mResizeObservers.AppendElement(aObserver); } +void ResizeObserverController::DetachFromDocument() { + mResizeObserverNotificationHelper->Unregister(); +} + void ResizeObserverController::Notify() { @@ -240,7 +241,10 @@ ResizeObserverController::GetShell() const ResizeObserverController::~ResizeObserverController() { - mResizeObserverNotificationHelper->Disconnect(); + MOZ_RELEASE_ASSERT( + !mResizeObserverNotificationHelper->IsRegistered(), + "Nothing else should keep a reference to our notification helper when we go away"); + mResizeObserverNotificationHelper->DetachFromOwner(); } } // namespace dom diff --git a/dom/base/ResizeObserverController.h b/dom/base/ResizeObserverController.h index 5d7912b438..01169112aa 100644 --- a/dom/base/ResizeObserverController.h +++ b/dom/base/ResizeObserverController.h @@ -41,6 +41,10 @@ public: void Disconnect(); + bool IsRegistered() const { return mRegistered; } + + void DetachFromOwner() { mOwner = nullptr; } + protected: virtual ~ResizeObserverNotificationHelper(); @@ -68,6 +72,7 @@ public: void Traverse(nsCycleCollectionTraversalCallback& aCb); void Unlink(); + void DetachFromDocument(); void AddResizeObserver(ResizeObserver* aObserver); /* diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index ce37c77b2c..0396848a99 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -3644,6 +3644,12 @@ nsDocument::DeleteShell() // objects for @font-face rules that came from the style set. RebuildUserFontSet(); + if (mResizeObserverController) { + // If the shell is going away, we need to remove any links to this document + // from the observer. + mResizeObserverController->DetachFromDocument(); + } + nsIPresShell* oldShell = mPresShell; mPresShell = nullptr; UpdateFrameRequestCallbackSchedulingState(oldShell); From e3f6690ee7202449b52e57f34d7695923e60a2dd Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 19 Oct 2020 19:35:03 +0000 Subject: [PATCH 2/7] Issue #1671 - Unprefix ::-moz-selection This actually keeps both pseudo-elements for now, since the prefixed version is still used internally, but we need the unprefixed version for web compat. Note: while unprefixing a non-spec-compliant pseudo here, it's exactly in line with what other browsers do. Nobody is following the spec here and at least we'll be doing what everyone else is with our unprefixed version. --- .../rules/test/browser_rules_pseudo-element_01.js | 6 +++--- devtools/shared/css/generated/properties-db.js | 1 + layout/generic/nsTextFrame.cpp | 11 +++++++++-- .../tests/test_getCSSPseudoElementNames.html | 1 + layout/style/nsCSSPseudoElementList.h | 3 +++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js index 77b8c06882..72cc7f8980 100644 --- a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js +++ b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js @@ -29,7 +29,7 @@ function* testTopLeft(inspector, view) { elementRulesNb: 4, firstLineRulesNb: 2, firstLetterRulesNb: 1, - selectionRulesNb: 0, + selectionRulesNb: 1, afterRulesNb: 1, beforeRulesNb: 2 } @@ -166,7 +166,7 @@ function* testParagraph(inspector, view) { elementRulesNb: 3, firstLineRulesNb: 1, firstLetterRulesNb: 1, - selectionRulesNb: 1, + selectionRulesNb: 2, beforeRulesNb: 0, afterRulesNb: 0 }); @@ -216,7 +216,7 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) { firstLetterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-letter"), selectionRules: elementStyle.rules.filter(rule => - rule.pseudoElement === ":-moz-selection"), + rule.pseudoElement === ":selection"), beforeRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":before"), afterRules: elementStyle.rules.filter(rule => diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js index 316352771a..50d849e79e 100644 --- a/devtools/shared/css/generated/properties-db.js +++ b/devtools/shared/css/generated/properties-db.js @@ -9375,6 +9375,7 @@ exports.PSEUDO_ELEMENTS = [ ":backdrop", ":first-letter", ":first-line", + ":selection", ":-moz-selection", ":-moz-focus-inner", ":-moz-focus-outer", diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index fcce7f3f65..4decdc8ec9 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -3947,11 +3947,18 @@ nsTextPaintStyle::InitSelectionColorsAndShadow() if (selectionElement && selectionStatus == nsISelectionController::SELECTION_ON) { RefPtr sc = nullptr; + // Probe for both selection and -moz-selection sc = mPresContext->StyleSet()-> ProbePseudoElementStyle(selectionElement, - CSSPseudoElementType::mozSelection, + CSSPseudoElementType::selection, mFrame->StyleContext()); - // Use -moz-selection pseudo class. + if (!sc) { + sc = mPresContext->StyleSet()-> + ProbePseudoElementStyle(selectionElement, + CSSPseudoElementType::mozSelection, + mFrame->StyleContext()); + } + // Use selection pseudo class. if (sc) { mSelectionBGColor = sc->GetVisitedDependentColor(eCSSProperty_background_color); diff --git a/layout/inspector/tests/test_getCSSPseudoElementNames.html b/layout/inspector/tests/test_getCSSPseudoElementNames.html index cdb4572d45..8879f21dc4 100644 --- a/layout/inspector/tests/test_getCSSPseudoElementNames.html +++ b/layout/inspector/tests/test_getCSSPseudoElementNames.html @@ -16,6 +16,7 @@ ":first-letter", ":first-line", ":placeholder", + ":selection", ":-moz-color-swatch", ":-moz-focus-inner", ":-moz-focus-outer", diff --git a/layout/style/nsCSSPseudoElementList.h b/layout/style/nsCSSPseudoElementList.h index 552c76734a..b8393d3952 100644 --- a/layout/style/nsCSSPseudoElementList.h +++ b/layout/style/nsCSSPseudoElementList.h @@ -37,6 +37,9 @@ CSS_PSEUDO_ELEMENT(firstLine, ":first-line", CSS_PSEUDO_ELEMENT_IS_CSS2 | CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS) +CSS_PSEUDO_ELEMENT(selection, ":selection", + CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS) +// Keep the prefixed version for now. CSS_PSEUDO_ELEMENT(mozSelection, ":-moz-selection", CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS) From 33e50615d9e76a9be4367d7826079613d87cfbd2 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Tue, 29 Sep 2020 11:31:46 -0500 Subject: [PATCH 3/7] Issue #1668 - Part 1: Implement support for caret-color property. This CSS property allows input carets (that blinking input cursor you see in text fields), to be given a custom color. This was implemented in Firefox 53, and it was such a minor feature that no one ever missed it, but I don't see any harm in implementing this. https://bugzilla.mozilla.org/show_bug.cgi?id=1063162 --- .../shared/css/generated/properties-db.js | 23 +++++++++++++++++++ layout/generic/nsFrame.cpp | 3 +-- layout/style/StyleAnimationValue.cpp | 12 +++++++--- layout/style/StyleComplexColor.h | 19 ++++++++++++--- layout/style/nsCSSPropList.h | 11 +++++++++ layout/style/nsComputedDOMStyle.cpp | 8 +++++++ layout/style/nsComputedDOMStyle.h | 1 + layout/style/nsComputedDOMStylePropertyList.h | 1 + layout/style/nsRuleNode.cpp | 15 ++++++++++-- layout/style/nsStyleStruct.cpp | 6 +++++ layout/style/nsStyleStruct.h | 1 + layout/style/test/property_database.js | 12 ++++++++++ .../test/test_transitions_per_property.html | 15 ++++++++++++ 13 files changed, 117 insertions(+), 10 deletions(-) diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js index 50d849e79e..01358a033d 100644 --- a/devtools/shared/css/generated/properties-db.js +++ b/devtools/shared/css/generated/properties-db.js @@ -2872,6 +2872,7 @@ exports.CSS_PROPERTIES = { "box-shadow", "box-sizing", "caption-side", + "caret-color", "clear", "clip", "clip-path", @@ -5277,6 +5278,28 @@ exports.CSS_PROPERTIES = { "unset" ] }, + "caret-color": { + "isInherited": true, + "subproperties": [ + "caret-color" + ], + "supports": [ + 2 + ], + "values": [ + "COLOR", + "auto", + "currentColor", + "hsl", + "hsla", + "inherit", + "initial", + "rgb", + "rgba", + "transparent", + "unset" + ] + }, "clear": { "isInherited": false, "subproperties": [ diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 72923c4b7f..7f67c7d684 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1831,8 +1831,7 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, nscolor nsIFrame::GetCaretColorAt(int32_t aOffset) { - // Use text color. - return StyleColor()->mColor; + return StyleColor()->CalcComplexColor(StyleUserInterface()->mCaretColor); } bool diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index ca0b1133f4..ff67835536 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -4468,8 +4468,12 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty, StyleDataAtOffset(styleStruct, ssOffset)); return true; case eStyleAnimType_ComplexColor: { - aComputedValue.SetComplexColorValue( - StyleDataAtOffset(styleStruct, ssOffset)); + auto& color = StyleDataAtOffset(styleStruct, ssOffset); + if (color.mIsAuto) { + aComputedValue.SetAutoValue(); + } else { + aComputedValue.SetComplexColorValue(color); + } return true; } case eStyleAnimType_PaintServer: { @@ -4782,7 +4786,9 @@ StyleAnimationValue::SetCurrentColorValue() void StyleAnimationValue::SetComplexColorValue(const StyleComplexColor& aColor) { - if (aColor.IsCurrentColor()) { + if (aColor.mIsAuto) { + SetAutoValue(); + } else if (aColor.IsCurrentColor()) { SetCurrentColorValue(); } else if (aColor.IsNumericColor()) { SetColorValue(aColor.mColor); diff --git a/layout/style/StyleComplexColor.h b/layout/style/StyleComplexColor.h index c6dd57a727..f3ff126a40 100644 --- a/layout/style/StyleComplexColor.h +++ b/layout/style/StyleComplexColor.h @@ -23,16 +23,29 @@ struct StyleComplexColor { nscolor mColor; uint8_t mForegroundRatio; + // Whether the complex color represents a computed-value time auto + // value. This is only a flag indicating that this value should not + // be interpolatable with other colors, while other fields still + // represents the actual used color of this value. + bool mIsAuto; - static StyleComplexColor FromColor(nscolor aColor) { return {aColor, 0}; } - static StyleComplexColor CurrentColor() { return {NS_RGBA(0, 0, 0, 0), 255}; } + static StyleComplexColor FromColor(nscolor aColor) { + return {aColor, 0, false}; + } + static StyleComplexColor CurrentColor() { + return {NS_RGBA(0, 0, 0, 0), 255, false}; + } + static StyleComplexColor Auto() { + return {NS_RGBA(0, 0, 0, 0), 255, true}; + } bool IsNumericColor() const { return mForegroundRatio == 0; } bool IsCurrentColor() const { return mForegroundRatio == 255; } bool operator==(const StyleComplexColor& aOther) const { return mForegroundRatio == aOther.mForegroundRatio && - (IsCurrentColor() || mColor == aOther.mColor); + (IsCurrentColor() || mColor == aOther.mColor) && + mIsAuto == aOther.mIsAuto; } bool operator!=(const StyleComplexColor& aOther) const { return !(*this == aOther); diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 8900192454..4f79db5a55 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -1394,6 +1394,17 @@ CSS_PROP_TABLEBORDER( kCaptionSideKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_Discrete) +CSS_PROP_USERINTERFACE( + caret-color, + caret_color, + CaretColor, + CSS_PROPERTY_PARSE_VALUE | + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED, + "", + VARIANT_AUTO | VARIANT_HC, + nullptr, + offsetof(nsStyleUserInterface, mCaretColor), + eStyleAnimType_ComplexColor) CSS_PROP_DISPLAY( clear, clear, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 610039fbaf..080932af23 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -4187,6 +4187,14 @@ nsComputedDOMStyle::DoGetUnicodeBidi() return val.forget(); } +already_AddRefed +nsComputedDOMStyle::DoGetCaretColor() +{ + RefPtr val = new nsROCSSPrimitiveValue; + SetValueFromComplexColor(val, StyleUserInterface()->mCaretColor); + return val.forget(); +} + already_AddRefed nsComputedDOMStyle::DoGetCursor() { diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 5af518c2eb..35a6142688 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -488,6 +488,7 @@ private: already_AddRefed DoGetShapeOutside(); /* User interface properties */ + already_AddRefed DoGetCaretColor(); already_AddRefed DoGetCursor(); already_AddRefed DoGetForceBrokenImageIcon(); already_AddRefed DoGetIMEMode(); diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index 5572818105..8d4d8e45e2 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -101,6 +101,7 @@ COMPUTED_STYLE_PROP(box_decoration_break, BoxDecorationBreak) COMPUTED_STYLE_PROP(box_shadow, BoxShadow) COMPUTED_STYLE_PROP(box_sizing, BoxSizing) COMPUTED_STYLE_PROP(caption_side, CaptionSide) +COMPUTED_STYLE_PROP(caret_color, CaretColor) COMPUTED_STYLE_PROP(clear, Clear) COMPUTED_STYLE_PROP(clip, Clip) COMPUTED_STYLE_PROP(color, Color) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index fb592abdd0..9e4e47dd92 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1151,13 +1151,16 @@ SetComplexColor(const nsCSSValue& aValue, aResult = StyleComplexColor::CurrentColor(); } else if (unit == eCSSUnit_ComplexColor) { aResult = aValue.GetStyleComplexColorValue(); + } else if (unit == eCSSUnit_Auto) { + aResult = StyleComplexColor::Auto(); } else { + nscolor resultColor; if (!SetColor(aValue, aParentColor.mColor, aPresContext, - nullptr, aResult.mColor, aConditions)) { + nullptr, resultColor, aConditions)) { MOZ_ASSERT_UNREACHABLE("Unknown color value"); return; } - aResult.mForegroundRatio = 0; + aResult = StyleComplexColor::FromColor(resultColor); } } @@ -5209,6 +5212,14 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, parentUI->mPointerEvents, NS_STYLE_POINTER_EVENTS_AUTO); + // caret-color: auto, color, inherit + const nsCSSValue* caretColorValue = aRuleData->ValueForCaretColor(); + SetComplexColor(*caretColorValue, + parentUI->mCaretColor, + StyleComplexColor::Auto(), + mPresContext, + ui->mCaretColor, conditions); + COMPUTE_END_INHERITED(UserInterface, ui) } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index cb70f03a3d..c0ea9c256c 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -4023,6 +4023,7 @@ nsStyleUserInterface::nsStyleUserInterface(StyleStructContext aContext) , mUserFocus(StyleUserFocus::None) , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO) , mCursor(NS_STYLE_CURSOR_AUTO) + , mCaretColor(StyleComplexColor::Auto()) { MOZ_COUNT_CTOR(nsStyleUserInterface); } @@ -4034,6 +4035,7 @@ nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) , mPointerEvents(aSource.mPointerEvents) , mCursor(aSource.mCursor) , mCursorImages(aSource.mCursorImages) + , mCaretColor(aSource.mCaretColor) { MOZ_COUNT_CTOR(nsStyleUserInterface); } @@ -4082,6 +4084,10 @@ nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const hint |= nsChangeHint_NeutralChange; } + if (mCaretColor != aNewData.mCaretColor) { + hint |= nsChangeHint_RepaintFrame; + } + return hint; } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index e4d02a24a7..88000c722a 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -3416,6 +3416,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface uint8_t mCursor; // [inherited] See nsStyleConsts.h nsTArray mCursorImages; // [inherited] images and coords + mozilla::StyleComplexColor mCaretColor; // [inherited] inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const; }; diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 1d830b188d..d647b57161 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2836,6 +2836,18 @@ var gCSSProperties = { other_values: [ "bottom", "left", "right", "top-outside", "bottom-outside" ], invalid_values: [] }, + "caret-color": { + domProp: "caretColor", + inherited: true, + type: CSS_TYPE_LONGHAND, + prerequisites: { "color": "black" }, + // Though "auto" is an independent computed-value time keyword value, + // it is not distinguishable from currentcolor because getComputedStyle + // always returns used value for . + initial_values: [ "auto", "currentcolor", "black", "rgb(0,0,0)" ], + other_values: [ "green", "transparent", "rgba(128,128,128,.5)", "#123" ], + invalid_values: [ "#0", "#00", "#00000", "cc00ff" ] + }, "clear": { domProp: "clear", inherited: false, diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html index 29e2ae24c2..f188f4f6fb 100644 --- a/layout/style/test/test_transitions_per_property.html +++ b/layout/style/test/test_transitions_per_property.html @@ -1373,6 +1373,21 @@ function test_true_currentcolor_transition(prop, get_color=(x => x), is_shorthan div.style.removeProperty("color"); } +function test_auto_color_transition(prop, get_color=(x => x), is_shorthand=false) { + const msg_prefix = `color-valued property ${prop}: `; + const test_color = "rgb(51, 102, 153)"; + div.style.setProperty("transition-property", "none", ""); + div.style.setProperty(prop, "auto", ""); + let used_value_of_auto = get_color(cs.getPropertyValue(prop)); + isnot(used_value_of_auto, test_color, + msg_prefix + "ensure used auto value is different than our test color"); + + div.style.setProperty("transition-property", prop, ""); + div.style.setProperty(prop, test_color, ""); + is(get_color(cs.getPropertyValue(prop)), test_color, + msg_prefix + "not interpolatable between auto and rgb color"); +} + function get_color_from_shorthand_value(value) { var m = value.match(/rgba?\([^, ]*, [^, ]*, [^, ]*(?:, [^, ]*)?\)/); isnot(m, null, "shorthand property value should contain color"); From 1f68b254688ec4eaa27f2a3bb19e2f4f8b9e1409 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Sun, 18 Oct 2020 10:12:53 -0500 Subject: [PATCH 4/7] Issue #1668 - Part 2: Visited color and auto support for caret-color property. Mozilla's original implementation of this failed a couple of tests, but this seems to solve all the problems. Basically, the caret-color wasn't able to be set differently based on whether a link was visited, and the auto value implementation was incomplete. The only test we fail now is the one where you have grey text on a grey background and the caret is supposed to be visible, but I think that may have been removed from the spec. Even if it wasn't, no other browser supports it anyway. --- dom/smil/nsSMILCSSProperty.cpp | 1 + layout/generic/nsFrame.cpp | 2 +- layout/style/nsRuleNode.cpp | 15 +++++++++------ layout/style/nsStyleContext.cpp | 17 ++++++++++++++++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/dom/smil/nsSMILCSSProperty.cpp b/dom/smil/nsSMILCSSProperty.cpp index def89ef9f6..bbe91b5408 100644 --- a/dom/smil/nsSMILCSSProperty.cpp +++ b/dom/smil/nsSMILCSSProperty.cpp @@ -194,6 +194,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSPropertyID aPropID) // writing-mode switch (aPropID) { + case eCSSProperty_caret_color: case eCSSProperty_clip: case eCSSProperty_clip_rule: case eCSSProperty_clip_path: diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 7f67c7d684..a9e6354abe 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1831,7 +1831,7 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, nscolor nsIFrame::GetCaretColorAt(int32_t aOffset) { - return StyleColor()->CalcComplexColor(StyleUserInterface()->mCaretColor); + return nsLayoutUtils::GetColor(this, eCSSProperty_caret_color); } bool diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 9e4e47dd92..c32369e9bb 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -5141,6 +5141,13 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, { COMPUTE_START_INHERITED(UserInterface, ui, parentUI) + auto setComplexColor = [&](const nsCSSValue* aValue, + StyleComplexColor nsStyleUserInterface::* aField) { + SetComplexColor(*aValue, parentUI->*aField, + StyleComplexColor::Auto(), + mPresContext, ui->*aField, conditions); + }; + // cursor: enum, url, inherit const nsCSSValue* cursorValue = aRuleData->ValueForCursor(); nsCSSUnit cursorUnit = cursorValue->GetUnit(); @@ -5213,12 +5220,8 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, NS_STYLE_POINTER_EVENTS_AUTO); // caret-color: auto, color, inherit - const nsCSSValue* caretColorValue = aRuleData->ValueForCaretColor(); - SetComplexColor(*caretColorValue, - parentUI->mCaretColor, - StyleComplexColor::Auto(), - mPresContext, - ui->mCaretColor, conditions); + setComplexColor(aRuleData->ValueForCaretColor(), + &nsStyleUserInterface::mCaretColor); COMPUTE_END_INHERITED(UserInterface, ui) } diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 4b1a14897a..38b422bd73 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -1255,6 +1255,17 @@ nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext, } } + // NB: Calling Peek on |this|, not |thisVis| (see above). + if (!change && PeekStyleUserInterface()) { + const nsStyleUserInterface *thisVisUserInterface = thisVis->StyleUserInterface(); + const nsStyleUserInterface *otherVisUserInterface = otherVis->StyleUserInterface(); + if (thisVisUserInterface->mCaretColor != + otherVisUserInterface->mCaretColor) { + change = true; + } + } + + if (change) { hint |= nsChangeHint_RepaintFrame; } @@ -1487,6 +1498,9 @@ ExtractColor(nsCSSPropertyID aProperty, case StyleAnimationValue::eUnit_ComplexColor: return Some(aStyleContext->StyleColor()-> CalcComplexColor(val.GetStyleComplexColorValue())); + case StyleAnimationValue::eUnit_Auto: + return Some(aStyleContext->StyleColor()-> + CalcComplexColor(StyleComplexColor::Auto())); default: return Nothing(); } @@ -1508,7 +1522,8 @@ static const ColorIndexSet gVisitedIndices[2] = { { 0, 0 }, { 1, 0 } }; nscolor nsStyleContext::GetVisitedDependentColor(nsCSSPropertyID aProperty) { - NS_ASSERTION(aProperty == eCSSProperty_color || + NS_ASSERTION(aProperty == eCSSProperty_caret_color || + aProperty == eCSSProperty_color || aProperty == eCSSProperty_background_color || aProperty == eCSSProperty_border_top_color || aProperty == eCSSProperty_border_right_color || From 962a17acb7c0f5a3a180bf223bd552f390214140 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 21 Oct 2020 20:35:07 +0000 Subject: [PATCH 5/7] [DOM Fetch] Improve stability of Fetch API. --- dom/fetch/FetchDriver.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 122875bb03..d18db2834b 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -708,10 +708,12 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, // about races. if (mObserver) { + // Need to keep mObserver alive. + RefPtr observer = mObserver; if (NS_IsMainThread()) { - mObserver->OnDataAvailable(); + observer->OnDataAvailable(); } else { - RefPtr runnable = new DataAvailableRunnable(mObserver); + RefPtr runnable = new DataAvailableRunnable(observer); nsresult rv = NS_DispatchToMainThread(runnable); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -719,12 +721,15 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, } } - uint32_t aRead; + // Explicitly initialized to 0 because in some cases nsStringInputStream may + // not write to aRead. + uint32_t aRead = 0; MOZ_ASSERT(mResponse); MOZ_ASSERT(mPipeOutputStream); // From "Main Fetch" step 17: SRI-part2. - if (mResponse->Type() != ResponseType::Error && + if (mResponse && + mResponse->Type() != ResponseType::Error && !mRequest->GetIntegrity().IsEmpty()) { MOZ_ASSERT(mSRIDataVerifier); From 078536b2bb66605ac76a5f8819695c0cd44c9212 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 21 Oct 2020 23:48:32 +0000 Subject: [PATCH 6/7] [DOM Fetch] Detect broken pipes and propagate that write error to the caller. --- dom/fetch/FetchDriver.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index d18db2834b..79bd5a0e39 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -771,6 +771,17 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, nsresult rv = aInputStream->ReadSegments(NS_CopySegmentToStream, mPipeOutputStream, aCount, &aRead); + + // If no data was read, it's possible the output stream is closed but the + // ReadSegments call followed its contract of returning NS_OK despite write + // errors. Unfortunately, nsIOutputStream has an ill-conceived contract when + // taken together with ReadSegments' contract, because the pipe will just + // NS_OK if we try and invoke its Write* functions ourselves with a 0 count. + // So we must just assume the pipe is broken. + if (aRead == 0 && aCount != 0) { + return NS_BASE_STREAM_CLOSED; + } + return rv; } From e77b184480bd31f08d1fa6d7adcf7e471b5745f5 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 22 Oct 2020 20:43:08 +0000 Subject: [PATCH 7/7] [DOM] When failing to create a channel and an image request, make sure to set the image blocking status appropriately. This is the same status as we do for known no-data protocols and ensures we treat these two cases the same. --- dom/base/nsImageLoadingContent.cpp | 6 +++++- layout/reftests/image/reftest.list | 2 ++ layout/reftests/image/unknown-protocol-ref.html | 1 + layout/reftests/image/unknown-protocol.html | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 layout/reftests/image/unknown-protocol-ref.html create mode 100644 layout/reftests/image/unknown-protocol.html diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 7ddc2184b6..1226ef22e1 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -932,8 +932,12 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, MOZ_ASSERT(!req, "Shouldn't have non-null request here"); // If we don't have a current URI, we might as well store this URI so people // know what we tried (and failed) to load. - if (!mCurrentRequest) + if (!mCurrentRequest) { mCurrentURI = aNewURI; + if (mImageBlockingStatus == nsIContentPolicy::ACCEPT) { + mImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST; + } + } FireEvent(NS_LITERAL_STRING("error")); FireEvent(NS_LITERAL_STRING("loadend")); diff --git a/layout/reftests/image/reftest.list b/layout/reftests/image/reftest.list index 1a610811d8..0eddb61fc3 100644 --- a/layout/reftests/image/reftest.list +++ b/layout/reftests/image/reftest.list @@ -126,3 +126,5 @@ fuzzy(1,1) == image-orientation-background.html?90&flip image-orientation-r == image-resize-percent-height.html image-resize-ref.html == image-resize-percent-width.html image-resize-ref.html + +== unknown-protocol.html unknown-protocol-ref.html diff --git a/layout/reftests/image/unknown-protocol-ref.html b/layout/reftests/image/unknown-protocol-ref.html new file mode 100644 index 0000000000..b5bb326eef --- /dev/null +++ b/layout/reftests/image/unknown-protocol-ref.html @@ -0,0 +1 @@ + diff --git a/layout/reftests/image/unknown-protocol.html b/layout/reftests/image/unknown-protocol.html new file mode 100644 index 0000000000..ef06881b7b --- /dev/null +++ b/layout/reftests/image/unknown-protocol.html @@ -0,0 +1 @@ +