From bd7e851076665683fc5a4ba6673ba47c4ec3ffe7 Mon Sep 17 00:00:00 2001 From: roytam1 Date: Wed, 20 Jul 2022 10:44:45 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1013814 - add inIDOMUtils.getRelativeRuleLine; r=heycam,pbrosset (60153c71f7) - Bug 1197930 - Add comments for getRuleLine and getRuleColumn. r=heycam (6c65131f95) - Bug 1157292 - include XBL stylesheets in the inspector's list of stylesheets, r=dholbert,heycam (f3ecad41c2) - Bug 1187409 - make CssPropertyIsShorthand handle CSS variables r=heycam (6dcba2f01b) - Bug 1142206 - Let GetSubpropertiesForCSSProperty handle custom property. r=heycam, r=pbrosset (f86eba559a) - Bug 1201136 - treat "currentColor" as a valid color. r=heycam (f868825389) - Bug 180118 - Part 5: Add a RestyleHintData outparam to HasAttributeDependentStyle for use with eRestyle_SomeDescendants. r=bzbarsky (fab0ecdf39) - Bug 1206356: Add mfbt/Random.h, implementing the xorshift128+ random number generator. r=waldo (1928e47e21) - Bug 1197421 - Fix promise worker proxy cleanup and update callers. r=catalinb (2128787815) - Bug 1197421 - Fetch resolver uses PromiseWorkerProxy. r=catalinb (d8611f0bcc) - Bug 1180118 - Part 7: Split out FindClosestRestyleRoot and allow passing in a pre-computed restyle root to AddPendingRestyle. r=bzbarsky (b783859d8a) - Bug 1180118 - Part 8: Keep track of the closest restyle root in AddPendingRestylesForDescendantsMatchingSelectors. r=bzbarsky (cf9d1b35b6) - Bug 1180118 - Part 9: Clear nsCSSSelector pointers in the pending restyle tracker if they might be stale. r=bzbarsky (13faac05f3) - Bug 1180118 - Part 10: Logging. r=bzbarsky (79f71825ca) - Bug 1180118 - Part 11: Use ReparentStyleContext even if eRestyle_SomeDescendants is used. r=bzbarsky (9f8e218aac) - Bug 1187851 patch 1 - Tests for making dynamic changes to filter and perspective change fixed position containing block for descendants. r=roc (82bbd8b750) - Bug 1187851 patch 2 - Cleanup to prepare for making dynamic changes to filter and perspective change fixed position containing block for descendants. r=roc (9fc38132ac) - Bug 1187851 patch 3 - Rename nsChangeHint_AddOrRemoveTransform to nsChangeHint_UpdateContainingBlock. r=roc (25e50c5ac5) - Bug 1187851 patch 5 - Make dynamic changes to perspective change fixed position containing block for descendants. r=roc (df51439c10) - Bug 1203766 - Part 1: Generate nsPresArena::ObjectIDs with a preprocessor-included file. r=bzbarsky (18e36acbd9) - Bug 1203766 - Part 2: Add an ArenaRefPtr class that can have its pointer cleared out when an object's owning nsPresArena goes away. r=bzbarsky (ff06cd91e0) - Bug 1203766 - Part 3: Add ArenaRefPtr support to nsStyleContext. r=bzbarsky (f1b52960f2) - Bug 1203766 - Part 4: Add a "restyle generation" counter, which increments whenever we process pending restyles. r=bzbarsky (b54d7e5ec9) - Bug 1203766 - Part 5: Rename nsComputedDOMStyle::mStyleContextHolder to mStyleContext. r=bzbarsky (5fa2d18667) - Bug 1203766 - Part 6: Cache resolved style contexts on nsComputedDOMStyle to avoid re-resolving if styles haven't changed. r=bzbarsky (de84fc67e7) - Bug 1203766 - Part 6.1: Clear cached style context on nsComputedDOMStyle when its element is moved. r=bzbarsky (d43394515a) - Bug 1203766 - Part 7: Test. r=bzbarsky (59c7ea8c81) - Bug 1203766 - Unified compilation fixes. (61137c44a5) - Bug 1151829 - Unbreak build on non-SPS platforms after bug 1093934. (e9188d7c56) - Bug 1202512 - Part 1: Add Element flags to record whether an eRestyle_SomeDescendants restyle is pending for it. r=bzbarsky (7f6dbef338) - Bug 1197620 - Part 1 - Stop all animations in destroyed frames. r=bbirtles (829b1635db) - Bug 1197620 - Part 2 tests that animation stop playing when its element is not displayed. r=bbirtles (87597b5125) - Bug 1190254 - Use same conditions to call ReparentStyleContext in RestyleUndisplayedNodes as in RestyleSelf. r=mats (7e778822b3) - Bug 1181011 - Don't use cached rule node structs for animations within pseudo-elements. r=dbaron a=abillings (966b351dcd) - Bug 1180120 - Part 1: Record on style contexts that reset style is explicitly inherited. r=dbaron (50b4f4e76a) - Bug 1180120 - Part 2: Move style-if-visited as well in nsStyleContext::Move (and assert that its parent is the same as the non-visited-style parent). r=dbaron (fd34448459) - Bug 1180120 - Part 3: Record on ElementRestyler whether we are at the root of a restyle. r=dbaron (edeb469544) - Bug 1180120 - Part 4: Add an outparam to CalcStyleDifference to indicate which struct pointers were identical. r=dbaron (1410e5ce05) - Bug 1180120 - Part 5: Factor out section of ElementRestyler::Restyle that calls AddPendingRestylesForDescendantsMatchingSelectors. r=dbaron (ab5b899c7f) - Bug 1180120 - Part 6: Replace HasSameCachedStyleData call with samePointerStructs bit tests. r=dbaron (3654cb6db8) - Bug 1180120 - Part 6.1: Factor out some of RestyleUndisplayedDescendants. r=dbaron (882a535699) - Bug 1180120 - Part 6.2: Refactor MaybeReframeFor{Before,After}Pseudo. r=dbaron (99ccd305ca) - Bug 1180120 - Part 7: Add eRestyleResult_StopWithStyleChange. r=dbaron (6626dd8133) - Bug 1192302 - Part 1: Make MustCheckUndisplayedContent take its frame as an argument. r=bzbarsky (7ae5bcc569) - Bug 1192302 - Part 2: Traverse the frame tree when processing eRestyle_SomeDescendants. r=bzbarsky (71b325d22e) - Bug 1206996: Use range-based 'for' syntax to iterate across nsFrameLists in RestyleManager. r=tn (a2c8e0fa73) - Bug 1163875 - ensure opacity animation in patterns results in redraws r=jwatt (7fd1f5c55a) - Bug 1180036 - Replace the warning that anonymous nodes should not be in child lists with an assert plus whitelisting of known-OK cases. r=bz (0c9dd01766) - Bug 1169440 patch 4 - Add comment to nsStylePadding::DifferenceAlwaysHandledForDescendants. r=heycam (2483adc4a0) - Bug 1169440 patch 5 - Adjust hints in CalcDifference methods to emit new nsChangeHint_ReflowChangesSizeOrPosition hint. r=heycam (b1ad73ab5f) - Bug 1169440 patch 6 - Add parameter to nsIFrame::FrameNeedsReflow to control handling of target being a reflow root. r=dholbert (c75a63eb67) - Bug 1169440 patch 7 - Pass parameter determined from style hint to FrameNeedsReflow. r=dholbert (ee02625c5a) - Bug 1198894: Use nsChangeHint_RepaintFrame instead of NS_STYLE_HINT_VISUAL to trigger simple repaints in nsStyleStruct.cpp CalcDifference methods. r=heycam (770bb3c11c) - Bug 417178 - "Google reader does not show subscribed topics in ff3b3 at certain zoom levels" [p=roc@ocallahan.org (Robert O'Callahan [roc]) r+sr=dbaron a1.9b5=mconnor] (a9b8541d23) - Bug 1203472 - [css-grid] Add missing |mIsSubgrid| check. r=simon.sapin@exyr.org (d68050a108) - Bug 1141919 - Fix incomplete line break suppression in ruby. r=dbaron (087a824358) - Bug 1157011 - Check line break suppression of BR frame from its parent frame. r=dholbert (5572f7bc56) - Bug 1134849 - For display:inline elements whose writing mode is orthogonal to their parent's, the computed value should become inline-block. r=dbaron (0df244841c) - Bug 1196887 - Compare the writing-mode property, not only whether it is horizontal or vertical, when deciding whether to compute display:inline as inline-block. r=dholbert (a0c4500a83) - Bug 1140198 - display:contents on the root element (but not else-where) should compute to 'block'. r=roc (606663d0c9) - Bug 1188061 - Pass the style context to nsStylePosition::CalcDifference so that it can take account of writing-mode where necessary. r=dbaron (6728d9d865) - Bug 1181907 (Part 1) - Make it possible to use nsGenericHashKey with free functions. r=heycam (c304448825) - Bug 1181907 (Part 2) - Make nsCSSProperty hashable. r=heycam (4fff3bb968) - Bug 1181907 (Part 3) - Add CSSVariableImageTable and use it to store ImageValues generated by CSS variables. r=heycam (8431589452) - Bug 1139723 - Turn on expensive style struct assertions for 1136010-1.html, and fix pref name typo. r=dbaron (f20387295b) - Bug 1151214 part 1 - Remove the optimization to ignore 'align-content' changes for single-line flex containers. It's invalid now that we'll support 'align-content' for other box types (grid). r=dbaron (aa21e1a3a4) - No bug. Add comment to nsStyleClipPath::ReleaseRef explaining why only one member is nulled out. r=me (NPOTB) (19d5eb5fb1) - Bug 1202993 - Remove the logical-direction-based keywords for caption-side, and instead interpret the old physical keywords as logical sides. r=dholbert (0f33c4a767) - Bug 1177149 - Don't force an invalidation for transform origin changes. r=dbaron (8a134525e0) - Bug 1191855 - Make the intrinsic size of + diff --git a/layout/reftests/writing-mode/abspos/1183431-orthogonal-modes-8-ref.html b/layout/reftests/writing-mode/abspos/1183431-orthogonal-modes-8-ref.html new file mode 100644 index 0000000000..33e90d3f80 --- /dev/null +++ b/layout/reftests/writing-mode/abspos/1183431-orthogonal-modes-8-ref.html @@ -0,0 +1,19 @@ + + + + + +
+
abc
+
diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 86c600c353..cea38f9a91 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -150,6 +150,9 @@ test-pref(dom.meta-viewport.enabled,true) test-pref(font.size.inflation.emPerLin == 1172774-percent-padding-4.html 1172774-percent-vertical-ref.html == 1174450-intrinsic-sizing.html 1174450-intrinsic-sizing-ref.html == 1175789-underline-overline-1.html 1175789-underline-overline-1-ref.html +== 1188061-1-nsChangeHint_ClearAncestorIntrinsics.html 1188061-1-nsChangeHint_ClearAncestorIntrinsics-ref.html +== 1188061-2-nsChangeHint_UpdateComputedBSize.html 1188061-2-nsChangeHint_UpdateComputedBSize-ref.html +== 1196887-1-computed-display-inline-block.html 1196887-1-computed-display-inline-block-ref.html # Suite of tests from Gérard Talbot in bug 1079151 include abspos/reftest.list diff --git a/layout/reftests/writing-mode/tables/reftest.list b/layout/reftests/writing-mode/tables/reftest.list index 35555b1b48..868f9e7d47 100644 --- a/layout/reftests/writing-mode/tables/reftest.list +++ b/layout/reftests/writing-mode/tables/reftest.list @@ -74,10 +74,6 @@ fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-pro fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-006.xht multicol-count-002-ref.xht fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-007.xht multicol-count-002-ref.xht -fuzzy-if(Android,255,38) == table-caption-block-start-1.html table-caption-block-start-1-ref.html -fuzzy-if(Android,255,38) == table-caption-block-end-1.html table-caption-block-end-1-ref.html -== table-caption-inline-start-1.html table-caption-inline-start-1-ref.html -== table-caption-inline-end-1.html table-caption-inline-end-1-ref.html fuzzy-if(Android,255,38) == table-caption-top-1.html table-caption-top-1-ref.html fuzzy-if(Android,255,38) == table-caption-bottom-1.html table-caption-bottom-1-ref.html == table-caption-left-1.html table-caption-left-1-ref.html diff --git a/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html deleted file mode 100644 index fd446c3f5b..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - -
-
-
table caption
-
- -
-
-
table caption
-
- -
-
-
table caption
-
- -
-
-
table caption
-
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-end-1.html b/layout/reftests/writing-mode/tables/table-caption-block-end-1.html deleted file mode 100644 index 645f7dc644..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-block-end-1.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - -
table caption
- - - - -
table caption
- - - - -
table caption
- - - - -
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html deleted file mode 100644 index d4f8ab717c..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - -
-
table caption
-
-
- -
-
table caption
-
-
- -
-
table caption
-
-
- -
-
table caption
-
-
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-start-1.html b/layout/reftests/writing-mode/tables/table-caption-block-start-1.html deleted file mode 100644 index f8a04bb67e..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-block-start-1.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - -
table caption
- - - - -
table caption
- - - - -
table caption
- - - - -
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html index 8ffc4937d5..ae36e72e88 100644 --- a/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html +++ b/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html @@ -44,11 +44,11 @@ body > div {
-
-
table caption
+
+
table caption
-
-
table caption
+
+
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html deleted file mode 100644 index d26b51e26a..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - -
-
-
table caption
-
- -
-
table caption
-
-
- -
-
-
table caption
-
- -
-
-
table caption
-
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html b/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html deleted file mode 100644 index 835d4a6f0a..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - -
table caption
- - - - -
table caption
- - - - -
table caption
- - - - -
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html deleted file mode 100644 index bbc533a0d1..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - -
-
table caption
-
-
- -
-
-
table caption
-
- -
-
table caption
-
-
- -
-
table caption
-
-
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html b/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html deleted file mode 100644 index 86f59a40a7..0000000000 --- a/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - -
table caption
- - - - -
table caption
- - - - -
table caption
- - - - -
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html index 7c10436c96..b9f46b0813 100644 --- a/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html +++ b/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html @@ -45,11 +45,21 @@ body > div {
-
table caption
-
+
table caption
+
+
+ +
+
table caption
+
-
-
table caption
+
table caption
+
+
+ +
+
table caption
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-left-1.html b/layout/reftests/writing-mode/tables/table-caption-left-1.html index 469fb2783c..1096bcaeb3 100644 --- a/layout/reftests/writing-mode/tables/table-caption-left-1.html +++ b/layout/reftests/writing-mode/tables/table-caption-left-1.html @@ -55,7 +55,17 @@ caption { + + + +
table caption
+
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html index 7a2b42cdd5..7e93276d1e 100644 --- a/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html +++ b/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html @@ -45,11 +45,21 @@ body > div {
-
-
table caption
+
+
table caption
+
+ +
+
+
table caption
-
table caption
-
+
+
table caption
+
+ +
+
+
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-right-1.html b/layout/reftests/writing-mode/tables/table-caption-right-1.html index d4e36485cf..e6a4cd7347 100644 --- a/layout/reftests/writing-mode/tables/table-caption-right-1.html +++ b/layout/reftests/writing-mode/tables/table-caption-right-1.html @@ -55,7 +55,17 @@ caption { + + + +
table caption
+
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html index 8c3ff8621f..ac90c6ec20 100644 --- a/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html +++ b/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html @@ -44,11 +44,11 @@ body > div {
-
table caption
-
+
table caption
+
-
table caption
-
+
table caption
+
diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 684ecf4eb5..4934cca722 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -198,7 +198,9 @@ CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* a } nsRestyleHint -CommonAnimationManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) +CommonAnimationManager::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) { return nsRestyleHint(0); } @@ -219,6 +221,7 @@ CommonAnimationManager::RulesMatching(ElementRuleProcessorData* aData) nsCSSPseudoElements::ePseudo_NotPseudoElement); if (rule) { aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); } } @@ -238,6 +241,7 @@ CommonAnimationManager::RulesMatching(PseudoElementRuleProcessorData* aData) nsIStyleRule *rule = GetAnimationRule(aData->mElement, aData->mPseudoType); if (rule) { aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); } } @@ -445,6 +449,15 @@ AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) // Don't apply transitions or animations to things inside of // pseudo-elements. // FIXME (Bug 522599): Add tests for this. + + // Prevent structs from being cached on the rule node since we're inside + // a pseudo-element, as we could determine cacheability differently + // when walking the rule tree for a style context that is not inside + // a pseudo-element. Note that nsRuleNode::GetStyle##name_ and GetStyleData + // will never look at cached structs when we're animating things inside + // a pseduo-element, so that we don't incorrectly return a struct that + // is only appropriate for non-pseudo-elements. + aRuleData->mConditions.SetUncacheable(); return; } diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index cdbbd9f110..701623be7b 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -48,7 +48,8 @@ public: virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override; virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override; + HasAttributeDependentStyle(AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual void RulesMatching(ElementRuleProcessorData* aData) override; virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override; diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp index ca754f2f6a..f7dc4dcc11 100644 --- a/layout/style/CSSStyleSheet.cpp +++ b/layout/style/CSSStyleSheet.cpp @@ -1731,6 +1731,15 @@ CSSStyleSheet::List(FILE* out, int32_t aIndent) const void CSSStyleSheet::ClearRuleCascades() { + // We might be in ClearRuleCascades because we had a modification + // to the sheet that resulted in an nsCSSSelector being destroyed. + // Tell the RestyleManager for each document we're used in + // so that they can drop any nsCSSSelector pointers (used for + // eRestyle_SomeDescendants) in their mPendingRestyles. + for (nsStyleSet* styleSet : mStyleSets) { + styleSet->ClearSelectors(); + } + bool removedSheetFromRuleProcessorCache = false; if (mRuleProcessors) { nsCSSRuleProcessor **iter = mRuleProcessors->Elements(), diff --git a/layout/style/CounterStyleManager.cpp b/layout/style/CounterStyleManager.cpp index 81d32317d3..95c52c4675 100644 --- a/layout/style/CounterStyleManager.cpp +++ b/layout/style/CounterStyleManager.cpp @@ -6,6 +6,7 @@ #include "CounterStyleManager.h" +#include "mozilla/ArenaObjectID.h" #include "mozilla/ArrayUtils.h" #include "mozilla/CheckedInt.h" #include "mozilla/MathAlgorithms.h" @@ -973,7 +974,7 @@ public: void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW { return aPresContext->PresShell()->AllocateByObjectID( - nsPresArena::DependentBuiltinCounterStyle_id, sz); + eArenaObjectID_DependentBuiltinCounterStyle, sz); } private: @@ -981,7 +982,7 @@ private: { nsIPresShell* shell = mManager->PresContext()->PresShell(); this->~DependentBuiltinCounterStyle(); - shell->FreeByObjectID(nsPresArena::DependentBuiltinCounterStyle_id, this); + shell->FreeByObjectID(eArenaObjectID_DependentBuiltinCounterStyle, this); } CounterStyleManager* mManager; @@ -1091,7 +1092,7 @@ public: void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW { return aPresContext->PresShell()->AllocateByObjectID( - nsPresArena::CustomCounterStyle_id, sz); + eArenaObjectID_CustomCounterStyle, sz); } private: @@ -1099,7 +1100,7 @@ private: { nsIPresShell* shell = mManager->PresContext()->PresShell(); this->~CustomCounterStyle(); - shell->FreeByObjectID(nsPresArena::CustomCounterStyle_id, this); + shell->FreeByObjectID(eArenaObjectID_CustomCounterStyle, this); } const nsTArray& GetSymbols(); diff --git a/layout/style/SVGAttrAnimationRuleProcessor.cpp b/layout/style/SVGAttrAnimationRuleProcessor.cpp index 3a1230f511..9eb31b1b23 100644 --- a/layout/style/SVGAttrAnimationRuleProcessor.cpp +++ b/layout/style/SVGAttrAnimationRuleProcessor.cpp @@ -62,7 +62,9 @@ SVGAttrAnimationRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessor } /* virtual */ nsRestyleHint -SVGAttrAnimationRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) +SVGAttrAnimationRuleProcessor::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) { return nsRestyleHint(0); } diff --git a/layout/style/SVGAttrAnimationRuleProcessor.h b/layout/style/SVGAttrAnimationRuleProcessor.h index 7a3fb65144..1750c761bd 100644 --- a/layout/style/SVGAttrAnimationRuleProcessor.h +++ b/layout/style/SVGAttrAnimationRuleProcessor.h @@ -44,7 +44,8 @@ public: virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override; virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override; + HasAttributeDependentStyle(AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_MUST_OVERRIDE override; diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 95eb154d96..fec9c46435 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -559,7 +559,7 @@ nsCSSSelector::ToString(nsAString& aString, CSSStyleSheet* aSheet, const nsCSSSelector *s = stack.ElementAt(index); stack.RemoveElementAt(index); - s->AppendToStringWithoutCombinators(aString, aSheet); + s->AppendToStringWithoutCombinators(aString, aSheet, false); // Append the combinator, if needed. if (!stack.IsEmpty()) { @@ -583,24 +583,85 @@ nsCSSSelector::ToString(nsAString& aString, CSSStyleSheet* aSheet, } void -nsCSSSelector::AppendToStringWithoutCombinators - (nsAString& aString, CSSStyleSheet* aSheet) const +nsCSSSelector::AppendToStringWithoutCombinators( + nsAString& aString, + CSSStyleSheet* aSheet, + bool aUseStandardNamespacePrefixes) const { - AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false); + AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false, + aUseStandardNamespacePrefixes); for (const nsCSSSelector* negation = mNegations; negation; negation = negation->mNegations) { aString.AppendLiteral(":not("); - negation->AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, - true); + negation->AppendToStringWithoutCombinatorsOrNegations( + aString, aSheet, true, aUseStandardNamespacePrefixes); aString.Append(char16_t(')')); } } +#ifdef DEBUG +nsCString +nsCSSSelector::RestrictedSelectorToString() const +{ + MOZ_ASSERT(IsRestrictedSelector()); + + nsString result; + AppendToStringWithoutCombinators(result, nullptr, true); + return NS_ConvertUTF16toUTF8(result); +} + +static bool +AppendStandardNamespacePrefixToString(nsAString& aString, int32_t aNameSpace) +{ + if (aNameSpace == kNameSpaceID_Unknown) { + // Wildcard namespace; no prefix to write. + return false; + } + switch (aNameSpace) { + case kNameSpaceID_None: + break; + case kNameSpaceID_XML: + aString.AppendLiteral("xml"); + break; + case kNameSpaceID_XHTML: + aString.AppendLiteral("html"); + break; + case kNameSpaceID_XLink: + aString.AppendLiteral("xlink"); + break; + case kNameSpaceID_XSLT: + aString.AppendLiteral("xsl"); + break; + case kNameSpaceID_XBL: + aString.AppendLiteral("xbl"); + break; + case kNameSpaceID_MathML: + aString.AppendLiteral("math"); + break; + case kNameSpaceID_RDF: + aString.AppendLiteral("rdf"); + break; + case kNameSpaceID_XUL: + aString.AppendLiteral("xul"); + break; + case kNameSpaceID_SVG: + aString.AppendLiteral("svg"); + break; + default: + aString.AppendLiteral("ns"); + aString.AppendInt(aNameSpace); + break; + } + return true; +} +#endif + void nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations (nsAString& aString, CSSStyleSheet* aSheet, - bool aIsNegated) const + bool aIsNegated, + bool aUseStandardNamespacePrefixes) const { nsAutoString temp; bool isPseudoElement = IsPseudoElement(); @@ -616,7 +677,18 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations // null, that means that the only namespaces we could have are the // wildcard namespace (which can be implicit in this case) and the "none" // namespace, which then needs to be explicitly specified. - if (!sheetNS) { + if (aUseStandardNamespacePrefixes) { +#ifdef DEBUG + // We have no sheet to look up prefix information from. This is + // only for debugging, so use some "standard" prefixes that + // are recognizable. + wroteNamespace = + AppendStandardNamespacePrefixToString(aString, mNameSpace); + if (wroteNamespace) { + aString.Append(char16_t('|')); + } +#endif + } else if (!sheetNS) { NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown || mNameSpace == kNameSpaceID_None, "How did we get this namespace?"); @@ -740,7 +812,12 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations aString.Append(char16_t('*')); aString.Append(char16_t('|')); } else if (list->mNameSpace != kNameSpaceID_None) { - if (aSheet) { + if (aUseStandardNamespacePrefixes) { +#ifdef DEBUG + AppendStandardNamespacePrefixToString(aString, list->mNameSpace); + aString.Append(char16_t('|')); +#endif + } else if (aSheet) { nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap(); nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace); // Default namespaces don't apply to attribute selectors, so diff --git a/layout/style/StyleRule.h b/layout/style/StyleRule.h index 8397e16ad9..317dafb335 100644 --- a/layout/style/StyleRule.h +++ b/layout/style/StyleRule.h @@ -159,22 +159,27 @@ public: void ToString(nsAString& aString, mozilla::CSSStyleSheet* aSheet, bool aAppend = false) const; -#ifdef DEBUG bool IsRestrictedSelector() const { return PseudoType() == nsCSSPseudoElements::ePseudo_NotPseudoElement; } + +#ifdef DEBUG + nsCString RestrictedSelectorToString() const; #endif private: void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass); nsCSSSelector* Clone(bool aDeepNext, bool aDeepNegations) const; - void AppendToStringWithoutCombinators(nsAString& aString, - mozilla::CSSStyleSheet* aSheet) const; - void AppendToStringWithoutCombinatorsOrNegations(nsAString& aString, - mozilla::CSSStyleSheet* aSheet, - bool aIsNegated) - const; + void AppendToStringWithoutCombinators( + nsAString& aString, + mozilla::CSSStyleSheet* aSheet, + bool aUseStandardNamespacePrefixes) const; + void AppendToStringWithoutCombinatorsOrNegations( + nsAString& aString, + mozilla::CSSStyleSheet* aSheet, + bool aIsNegated, + bool aUseStandardNamespacePrefixes) const; // Returns true if this selector can have a namespace specified (which // happens if and only if the default namespace would apply to this // selector). diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 50ff0a30fb..19aff1c33f 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -546,6 +546,22 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, return GetAnimationRule(aElement, aStyleContext->GetPseudoType()); } +void +nsAnimationManager::StopAnimationsForElement( + mozilla::dom::Element* aElement, + nsCSSPseudoElements::Type aPseudoType) +{ + MOZ_ASSERT(aElement); + AnimationCollection* collection = + GetAnimations(aElement, aPseudoType, false); + if (!collection) { + return; + } + + nsAutoAnimationMutationBatch mb(aElement->OwnerDoc()); + collection->Destroy(); +} + struct KeyframeData { float mKey; uint32_t mIndex; // store original order since sort algorithm is not stable diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 1eaf6b7ebd..8d924d9af7 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -308,6 +308,12 @@ public: void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); } void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); } + // Stop animations on the element. This method takes the real element + // rather than the element for the generated content for animations on + // ::before and ::after. + void StopAnimationsForElement(mozilla::dom::Element* aElement, + nsCSSPseudoElements::Type aPseudoType); + protected: virtual ~nsAnimationManager() {} diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 350eaf4894..e08a279650 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -149,10 +149,6 @@ CSS_KEY(bidi-override, bidi_override) CSS_KEY(blink, blink) CSS_KEY(block, block) CSS_KEY(block-axis, block_axis) -CSS_KEY(block-end, block_end) -CSS_KEY(block-end-outside, block_end_outside) -CSS_KEY(block-start, block_start) -CSS_KEY(block-start-outside, block_start_outside) CSS_KEY(blur, blur) CSS_KEY(bold, bold) CSS_KEY(bold-fraktur, bold_fraktur) @@ -310,10 +306,8 @@ CSS_KEY(initial, initial) CSS_KEY(inline, inline) CSS_KEY(inline-axis, inline_axis) CSS_KEY(inline-block, inline_block) -CSS_KEY(inline-end, inline_end) CSS_KEY(inline-flex, inline_flex) CSS_KEY(inline-grid, inline_grid) -CSS_KEY(inline-start, inline_start) CSS_KEY(inline-table, inline_table) CSS_KEY(inset, inset) CSS_KEY(inside, inside) diff --git a/layout/style/nsCSSProperty.h b/layout/style/nsCSSProperty.h index 79d92a6887..0e0536da78 100644 --- a/layout/style/nsCSSProperty.h +++ b/layout/style/nsCSSProperty.h @@ -8,6 +8,8 @@ #ifndef nsCSSProperty_h___ #define nsCSSProperty_h___ +#include + /* Declare the enum list using the magic of preprocessing enum values are "eCSSProperty_foo" (where foo is the property) @@ -64,6 +66,17 @@ enum nsCSSProperty { eCSSPropertyExtra_variable }; +namespace mozilla { + +template<> +inline PLDHashNumber +Hash(const nsCSSProperty& aValue) +{ + return uint32_t(aValue); +} + +} // namespace mozilla + // The "descriptors" that can appear in a @font-face rule. // They have the syntax of properties but different value rules. enum nsCSSFontDesc { diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index a93a6f6a49..19429221f5 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -916,12 +916,6 @@ const KTableValue nsCSSProps::kBoxSizingKTable[] = { }; const KTableValue nsCSSProps::kCaptionSideKTable[] = { - eCSSKeyword_block_start, NS_STYLE_CAPTION_SIDE_BSTART, - eCSSKeyword_block_end, NS_STYLE_CAPTION_SIDE_BEND, - eCSSKeyword_inline_start, NS_STYLE_CAPTION_SIDE_ISTART, - eCSSKeyword_inline_end, NS_STYLE_CAPTION_SIDE_IEND, - eCSSKeyword_block_start_outside, NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE, - eCSSKeyword_block_end_outside, NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE, eCSSKeyword_top, NS_STYLE_CAPTION_SIDE_TOP, eCSSKeyword_right, NS_STYLE_CAPTION_SIDE_RIGHT, eCSSKeyword_bottom, NS_STYLE_CAPTION_SIDE_BOTTOM, diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index c8acc39826..6fd8df9b63 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -2832,7 +2832,9 @@ EnumerateSelectors(nsTArray& aSelectors, AttributeEnumData* aDat } nsRestyleHint -nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) +nsCSSRuleProcessor::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) { // We could try making use of aData->mModType, but :not rules make it a bit // of a pain to do so... So just ignore it for now. diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index a60af54228..3fc709b284 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -144,7 +144,9 @@ public: virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override; + HasAttributeDependentStyle(AttributeRuleProcessorData* aData, + mozilla::RestyleHintData& aRestyleHintDataResult) + override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index d45f571ec9..79e639ba11 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -222,7 +222,9 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement, : mDocumentWeak(nullptr), mOuterFrame(nullptr), mInnerFrame(nullptr), mPresShell(nullptr), mStyleType(aStyleType), - mExposeVisitedStyle(false) + mStyleContextGeneration(0), + mExposeVisitedStyle(false), + mResolvedStyleContext(false) { MOZ_ASSERT(aElement && aPresShell); @@ -262,9 +264,23 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement, nsComputedDOMStyle::~nsComputedDOMStyle() { + ClearStyleContext(); } -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsComputedDOMStyle, mContent) +NS_IMPL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsComputedDOMStyle) + tmp->ClearStyleContext(); // remove observer before clearing mContent + NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsComputedDOMStyle) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsComputedDOMStyle) NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsComputedDOMStyle) return tmp->IsBlack(); @@ -281,6 +297,7 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END // QueryInterface implementation for nsComputedDOMStyle NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsComputedDOMStyle) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) @@ -333,7 +350,7 @@ nsComputedDOMStyle::GetLength(uint32_t* aLength) // Make sure we have up to date style so that we can include custom // properties. UpdateCurrentStyleSources(false); - if (mStyleContextHolder) { + if (mStyleContext) { length += StyleVariables()->mVariables.Count(); } @@ -572,13 +589,39 @@ nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv aCSSParseEnv.mPrincipal = nullptr; } +void +nsComputedDOMStyle::ClearStyleContext() +{ + if (mResolvedStyleContext) { + mResolvedStyleContext = false; + mContent->RemoveMutationObserver(this); + } + mStyleContext = nullptr; +} + +void +nsComputedDOMStyle::SetResolvedStyleContext(nsRefPtr&& aContext) +{ + if (!mResolvedStyleContext) { + mResolvedStyleContext = true; + mContent->AddMutationObserver(this); + } + mStyleContext = aContext; +} + +void +nsComputedDOMStyle::SetFrameStyleContext(nsStyleContext* aContext) +{ + ClearStyleContext(); + mStyleContext = aContext; +} + void nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) { - MOZ_ASSERT(!mStyleContextHolder); - nsCOMPtr document = do_QueryReferent(mDocumentWeak); if (!document) { + ClearStyleContext(); return; } @@ -601,11 +644,25 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) mPresShell = document->GetShell(); if (!mPresShell || !mPresShell->GetPresContext()) { + ClearStyleContext(); return; } + uint64_t currentGeneration = + mPresShell->GetPresContext()->GetRestyleGeneration(); + + if (mStyleContext) { + if (mStyleContextGeneration == currentGeneration) { + // Our cached style context is still valid. + return; + } + // We've processed some restyles, so the cached style context might + // be out of date. + mStyleContext = nullptr; + } + // XXX the !mContent->IsHTMLElement(nsGkAtoms::area) - // check is needed due to bug 135040 (to avoid using + // check is needed due to bug 135040 (to avoid using // mPrimaryFrame). Remove it once that's fixed. if (!mPseudo && mStyleType == eAll && !mContent->IsHTMLElement(nsGkAtoms::area)) { @@ -623,19 +680,19 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) "the inner table"); } - mStyleContextHolder = mInnerFrame->StyleContext(); - NS_ASSERTION(mStyleContextHolder, "Frame without style context?"); + SetFrameStyleContext(mInnerFrame->StyleContext()); + NS_ASSERTION(mStyleContext, "Frame without style context?"); } } - if (!mStyleContextHolder || mStyleContextHolder->HasPseudoElementData()) { + if (!mStyleContext || mStyleContext->HasPseudoElementData()) { #ifdef DEBUG - if (mStyleContextHolder) { + if (mStyleContext) { // We want to check that going through this path because of // HasPseudoElementData is rare, because it slows us down a good // bit. So check that we're really inside something associated // with a pseudo-element that contains elements. - nsStyleContext *topWithPseudoElementData = mStyleContextHolder; + nsStyleContext* topWithPseudoElementData = mStyleContext; while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) { topWithPseudoElementData = topWithPseudoElementData->GetParent(); } @@ -651,17 +708,26 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) } #endif // Need to resolve a style context - mStyleContextHolder = + nsRefPtr resolvedStyleContext = nsComputedDOMStyle::GetStyleContextForElementNoFlush( mContent->AsElement(), mPseudo, presShellForContent ? presShellForContent.get() : mPresShell, mStyleType); - if (!mStyleContextHolder) { + if (!resolvedStyleContext) { + ClearStyleContext(); return; } - NS_ASSERTION(mPseudo || !mStyleContextHolder->HasPseudoElementData(), + // No need to re-get the generation, even though GetStyleContextForElement + // will flush, since we flushed style at the top of this function. + NS_ASSERTION(mPresShell && + currentGeneration == + mPresShell->GetPresContext()->GetRestyleGeneration(), + "why should we have flushed style again?"); + + SetResolvedStyleContext(Move(resolvedStyleContext)); + NS_ASSERTION(mPseudo || !mStyleContext->HasPseudoElementData(), "should not have pseudo-element data"); } @@ -669,10 +735,10 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) // require chrome privilege. MOZ_ASSERT(!mExposeVisitedStyle || nsContentUtils::IsCallerChrome(), "mExposeVisitedStyle set incorrectly"); - if (mExposeVisitedStyle && mStyleContextHolder->RelevantLinkVisited()) { - nsStyleContext *styleIfVisited = mStyleContextHolder->GetStyleIfVisited(); + if (mExposeVisitedStyle && mStyleContext->RelevantLinkVisited()) { + nsStyleContext *styleIfVisited = mStyleContext->GetStyleIfVisited(); if (styleIfVisited) { - mStyleContextHolder = styleIfVisited; + mStyleContext = styleIfVisited; } } } @@ -684,9 +750,12 @@ nsComputedDOMStyle::ClearCurrentStyleSources() mInnerFrame = nullptr; mPresShell = nullptr; - // Release the current style context for it should be re-resolved - // whenever a frame is not available. - mStyleContextHolder = nullptr; + // Release the current style context if we got it off the frame. + // For a style context we resolved, keep it around so that we + // can re-use it next time this object is queried. + if (!mResolvedStyleContext) { + mStyleContext = nullptr; + } } already_AddRefed @@ -733,7 +802,7 @@ nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName, ErrorRes } UpdateCurrentStyleSources(needsLayoutFlush); - if (!mStyleContextHolder) { + if (!mStyleContext) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } @@ -802,7 +871,7 @@ nsComputedDOMStyle::IndexedGetter(uint32_t aIndex, bool& aFound, // Custom properties are exposed with indexed properties just after all // of the built-in properties. UpdateCurrentStyleSources(false); - if (!mStyleContextHolder) { + if (!mStyleContext) { aFound = false; return; } @@ -1277,8 +1346,8 @@ nsComputedDOMStyle::DoGetTransform() RuleNodeCacheConditions dummy; gfx::Matrix4x4 matrix = nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead, - mStyleContextHolder, - mStyleContextHolder->PresContext(), + mStyleContext, + mStyleContext->PresContext(), dummy, refBox, float(mozilla::AppUnitsPerCSSPixel())); @@ -3827,7 +3896,7 @@ nsComputedDOMStyle::DoGetAlignSelf() if (computedAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) { // "align-self: auto" needs to compute to parent's align-items value. - nsStyleContext* parentStyleContext = mStyleContextHolder->GetParent(); + nsStyleContext* parentStyleContext = mStyleContext->GetParent(); if (parentStyleContext) { computedAlignSelf = parentStyleContext->StylePosition()->mAlignItems; @@ -3926,7 +3995,7 @@ nsComputedDOMStyle::DoGetJustifyItems() nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue; nsAutoString str; auto justify = StylePosition()-> - ComputedJustifyItems(StyleDisplay(), mStyleContextHolder->GetParent()); + ComputedJustifyItems(StyleDisplay(), mStyleContext->GetParent()); nsCSSValue::AppendAlignJustifyValueToString(justify, str); val->SetString(str); return val; @@ -4659,7 +4728,7 @@ nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord) // lie about font size inflation since we lie about font size (since // the inflation only applies to text) - aCoord = nsHTMLReflowState::CalcLineHeight(mContent, mStyleContextHolder, + aCoord = nsHTMLReflowState::CalcLineHeight(mContent, mStyleContext, blockHeight, 1.0f); // CalcLineHeight uses font->mFont.size, but we want to use @@ -6008,6 +6077,17 @@ nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName) return val; } +void +nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent) +{ + NS_ASSERTION(mContent == aContent, "didn't we register mContent?"); + NS_ASSERTION(mResolvedStyleContext, + "should have only registered an observer when " + "mResolvedStyleContext is true"); + + ClearStyleContext(); +} + /* static */ nsComputedStyleMap* nsComputedDOMStyle::GetComputedStyleMap() { diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 0c6ede7c89..6d35c6ecd8 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -9,6 +9,8 @@ #define nsComputedDOMStyle_h__ #include "nsAutoPtr.h" +#include "mozilla/ArenaRefPtr.h" +#include "mozilla/ArenaRefPtrInlines.h" #include "mozilla/Attributes.h" #include "nsCOMPtr.h" #include "nscore.h" @@ -43,6 +45,7 @@ class nsStyleSides; struct nsTimingFunction; class nsComputedDOMStyle final : public nsDOMCSSDeclaration + , public nsStubMutationObserver { public: typedef nsCSSProps::KTableValue KTableValue; @@ -108,6 +111,9 @@ public: static void RegisterPrefChangeCallbacks(); static void UnregisterPrefChangeCallbacks(); + // nsIMutationObserver + NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED + private: virtual ~nsComputedDOMStyle(); @@ -122,13 +128,18 @@ private: mozilla::dom::CSSValue* CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue, const KTableValue aTable[]); - // This indicates error by leaving mStyleContextHolder null. + // This indicates error by leaving mStyleContext null. void UpdateCurrentStyleSources(bool aNeedsLayoutFlush); void ClearCurrentStyleSources(); + // Helper functions called by UpdateCurrentStyleSources. + void ClearStyleContext(); + void SetResolvedStyleContext(nsRefPtr&& aContext); + void SetFrameStyleContext(nsStyleContext* aContext); + #define STYLE_STRUCT(name_, checkdata_cb_) \ const nsStyle##name_ * Style##name_() { \ - return mStyleContextHolder->Style##name_(); \ + return mStyleContext->Style##name_(); \ } #include "nsStyleStructList.h" #undef STYLE_STRUCT @@ -600,12 +611,23 @@ private: nsWeakPtr mDocumentWeak; nsCOMPtr mContent; - /* - * Strong reference to the style context while we're accessing the data from - * it. This can be either a style context we resolved ourselves or a style - * context we got from our frame. + /** + * Strong reference to the style context we access data from. This can be + * either a style context we resolved ourselves or a style context we got + * from our frame. + * + * If we got the style context from the frame, we clear out mStyleContext + * in ClearCurrentStyleSources. If we resolved one ourselves, then + * ClearCurrentStyleSources leaves it in mStyleContext for use the next + * time this nsComputedDOMStyle object is queried. UpdateCurrentStyleSources + * in this case will check that the style context is still valid to be used, + * by checking whether flush styles results in any restyles having been + * processed. + * + * Since an ArenaRefPtr is used to hold the style context, it will be cleared + * if the pres arena from which it was allocated goes away. */ - nsRefPtr mStyleContextHolder; + mozilla::ArenaRefPtr mStyleContext; nsCOMPtr mPseudo; /* @@ -631,8 +653,20 @@ private: */ StyleType mStyleType; + /** + * The nsComputedDOMStyle generation at the time we last resolved a style + * context and stored it in mStyleContext. + */ + uint64_t mStyleContextGeneration; + bool mExposeVisitedStyle; + /** + * Whether we resolved a style context last time we called + * UpdateCurrentStyleSources. Initially false. + */ + bool mResolvedStyleContext; + #ifdef DEBUG bool mFlushedPendingReflows; #endif diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 9cde112e2b..a8669a6075 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -144,7 +144,9 @@ nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aDat // Test if style is dependent on attribute /* virtual */ nsRestyleHint -nsHTMLCSSStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) +nsHTMLCSSStyleSheet::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) { // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but // it doesn't really matter. diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index f1ecf2fe42..234f3e24cd 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -43,7 +43,8 @@ public: virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override; virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override; + HasAttributeDependentStyle(AttributeRuleProcessorData* aData, + mozilla::RestyleHintData& aRestyleHintDataResult) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_MUST_OVERRIDE override; diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 39f9e665ae..36c61c2fe5 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -335,7 +335,9 @@ nsHTMLStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) } /* virtual */ nsRestyleHint -nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) +nsHTMLStyleSheet::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) { // Do nothing on before-change checks if (!aData->mAttrHasChanged) { diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index 5ada9333bb..390cfb782b 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -45,7 +45,8 @@ public: virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override; virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override; + HasAttributeDependentStyle(AttributeRuleProcessorData* aData, + mozilla::RestyleHintData& aRestyleHintDataResult) override; virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_MUST_OVERRIDE override; diff --git a/layout/style/nsIStyleRuleProcessor.h b/layout/style/nsIStyleRuleProcessor.h index 00182dd380..2075050d40 100644 --- a/layout/style/nsIStyleRuleProcessor.h +++ b/layout/style/nsIStyleRuleProcessor.h @@ -115,8 +115,9 @@ public: * only, and may err on the side of reporting more dependencies than * really exist. */ - virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData) = 0; + virtual nsRestyleHint HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + mozilla::RestyleHintData& aRestyleHintDataResult) = 0; /** * Do any processing that needs to happen as a result of a change in diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index e0c5ffcbb8..f264493e73 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1402,7 +1402,7 @@ void* nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW { // Check the recycle list first. - return aPresContext->PresShell()->AllocateByObjectID(nsPresArena::nsRuleNode_id, sz); + return aPresContext->PresShell()->AllocateByObjectID(eArenaObjectID_nsRuleNode, sz); } // Overridden to prevent the global delete from being called, since the memory @@ -1457,7 +1457,7 @@ nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail) // Don't let the memory be freed, since it will be recycled // instead. Don't call the global operator delete. - mPresContext->PresShell()->FreeByObjectID(nsPresArena::nsRuleNode_id, this); + mPresContext->PresShell()->FreeByObjectID(eArenaObjectID_nsRuleNode, this); } nsRuleNode* nsRuleNode::CreateRootNode(nsPresContext* aPresContext) @@ -1475,7 +1475,8 @@ nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent, mNextSibling(nullptr), mDependentBits((uint32_t(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) | (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)), - mNoneBits(0), + mNoneBits(aParent ? aParent->mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA : + 0), mRefCnt(0) { MOZ_ASSERT(aContext); @@ -2754,6 +2755,14 @@ nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContex /* We can't be cached in the rule node. We have to be put right */ \ /* on the style context. */ \ aContext->SetStyle(eStyleStruct_##type_, data_); \ + if (aContext->GetParent()) { \ + /* This is pessimistic; we could be uncacheable because we had a */ \ + /* relative font-weight, for example, which does not need to defeat */ \ + /* the restyle optimizations in RestyleManager.cpp that look at */ \ + /* NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE. */ \ + aContext->GetParent()-> \ + AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE); \ + } \ } \ \ return data_; @@ -4357,13 +4366,13 @@ nsRuleNode::ComputeTextData(void* aStartStruct, parentText->mTextCombineUpright, NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE, 0, 0, 0, 0); - // -moz-text-discard: enum, inherit, initial + // -moz-control-character-visibility: enum, inherit, initial SetDiscrete(*aRuleData->ValueForControlCharacterVisibility(), text->mControlCharacterVisibility, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mControlCharacterVisibility, - NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN, 0, 0, 0, 0); + NS_STYLE_CONTROL_CHARACTER_VISIBILITY_VISIBLE, 0, 0, 0, 0); COMPUTE_END_INHERITED(Text, text) } @@ -8015,7 +8024,7 @@ nsRuleNode::ComputeTableBorderData(void* aStartStruct, table->mCaptionSide, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentTable->mCaptionSide, - NS_STYLE_CAPTION_SIDE_BSTART, 0, 0, 0, 0); + NS_STYLE_CAPTION_SIDE_TOP, 0, 0, 0, 0); // empty-cells: enum, inherit, initial SetDiscrete(*aRuleData->ValueForEmptyCells(), @@ -9347,9 +9356,14 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, "in some way."); const void *data; - data = mStyleData.GetStyleData(aSID, aContext); - if (MOZ_LIKELY(data != nullptr)) - return data; // We have a fully specified struct. Just return it. + + // Never use cached data for animated style inside a pseudo-element; + // see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto. + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { + data = mStyleData.GetStyleData(aSID, aContext); + if (MOZ_LIKELY(data != nullptr)) + return data; // We have a fully specified struct. Just return it. + } if (MOZ_UNLIKELY(!aComputeData)) return nullptr; @@ -9805,3 +9819,10 @@ nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, MOZ_ASSERT(ok || !(aPresContext && aStyleContext)); return ok; } + +/* static */ bool +nsRuleNode::ParentHasPseudoElementData(nsStyleContext* aContext) +{ + nsStyleContext* parent = aContext->GetParent(); + return parent && parent->HasPseudoElementData(); +} diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 854719adb9..3e8014e5bf 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -11,6 +11,7 @@ #ifndef nsRuleNode_h___ #define nsRuleNode_h___ +#include "mozilla/ArenaObjectID.h" #include "mozilla/PodOperations.h" #include "mozilla/RangedArray.h" #include "mozilla/RuleNodeCacheConditions.h" @@ -35,7 +36,7 @@ struct nsInheritedStyleData void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsInheritedStyleData_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsInheritedStyleData, sz); } void DestroyStructs(uint64_t aBits, nsPresContext* aContext) { @@ -54,7 +55,7 @@ struct nsInheritedStyleData void Destroy(uint64_t aBits, nsPresContext* aContext) { DestroyStructs(aBits, aContext); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsInheritedStyleData_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsInheritedStyleData, this); } nsInheritedStyleData() { @@ -83,7 +84,7 @@ struct nsResetStyleData void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsResetStyleData_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsResetStyleData, sz); } void Destroy(uint64_t aBits, nsPresContext* aContext) { @@ -99,7 +100,7 @@ struct nsResetStyleData #undef STYLE_STRUCT_INHERITED aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsResetStyleData_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsResetStyleData, this); } }; @@ -117,8 +118,8 @@ struct nsConditionalResetStyleData : mConditions(aConditions), mStyleStruct(aStyleStruct), mNext(aNext) {} void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { - return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsConditionalResetStyleDataEntry_id, sz); + return aContext->PresShell()->AllocateByObjectID( + mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, sz); } const mozilla::RuleNodeCacheConditions mConditions; @@ -146,8 +147,8 @@ struct nsConditionalResetStyleData } void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { - return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsConditionalResetStyleData_id, sz); + return aContext->PresShell()->AllocateByObjectID( + mozilla::eArenaObjectID_nsConditionalResetStyleData, sz); } void* GetStyleData(nsStyleStructID aSID) const { @@ -221,7 +222,7 @@ struct nsConditionalResetStyleData static_cast(e->mStyleStruct)->Destroy(aContext); \ Entry* next = e->mNext; \ aContext->PresShell()->FreeByObjectID( \ - nsPresArena::nsConditionalResetStyleDataEntry_id, e); \ + mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, e); \ e = next; \ } while (e); \ } \ @@ -233,8 +234,8 @@ struct nsConditionalResetStyleData #undef STYLE_STRUCT_RESET #undef STYLE_STRUCT_INHERITED - aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsConditionalResetStyleData_id, this); + aContext->PresShell()->FreeByObjectID( + mozilla::eArenaObjectID_nsConditionalResetStyleData, this); } }; @@ -843,6 +844,29 @@ public: return (mDependentBits & NS_RULE_NODE_USED_DIRECTLY) != 0; } + /** + * Is the mRule of this rule node an AnimValuesStyleRule? + */ + void SetIsAnimationRule() { + MOZ_ASSERT(!HaveChildren() || + (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE), + "SetIsAnimationRule must only set the IS_ANIMATION_RULE bit " + "before the rule node has children"); + mDependentBits |= NS_RULE_NODE_IS_ANIMATION_RULE; + mNoneBits |= NS_RULE_NODE_HAS_ANIMATION_DATA; + } + bool IsAnimationRule() const { + return (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE) != 0; + } + + /** + * Is the mRule of this rule node or any of its ancestors an + * AnimValuesStyleRule? + */ + bool HasAnimationData() const { + return (mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA) != 0; + } + // NOTE: Does not |AddRef|. Null only for the root. nsIStyleRule* GetRule() const { return mRule; } // NOTE: Does not |AddRef|. Never null. @@ -866,9 +890,14 @@ public: "in some way."); \ \ const nsStyle##name_ *data; \ - data = mStyleData.GetStyle##name_(); \ - if (MOZ_LIKELY(data != nullptr)) \ - return data; \ + \ + /* Never use cached data for animated style inside a pseudo-element; */ \ + /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \ + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { \ + data = mStyleData.GetStyle##name_(); \ + if (MOZ_LIKELY(data != nullptr)) \ + return data; \ + } \ \ if (!aComputeData) \ return nullptr; \ @@ -891,9 +920,14 @@ public: "in some way."); \ \ const nsStyle##name_ *data; \ - data = mStyleData.GetStyle##name_(aContext); \ - if (MOZ_LIKELY(data != nullptr)) \ - return data; \ + \ + /* Never use cached data for animated style inside a pseudo-element; */ \ + /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \ + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { \ + data = mStyleData.GetStyle##name_(aContext); \ + if (MOZ_LIKELY(data != nullptr)) \ + return data; \ + } \ \ if (!aComputeData) \ return nullptr; \ @@ -1017,6 +1051,8 @@ public: nsPresContext* aPresContext, nsStyleContext* aStyleContext, nscolor& aResult); + + static bool ParentHasPseudoElementData(nsStyleContext* aContext); }; #endif diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index b4a61ec061..80be81f420 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -957,18 +957,16 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_TABLE_EMPTY_CELLS_HIDE 0 #define NS_STYLE_TABLE_EMPTY_CELLS_SHOW 1 -#define NS_STYLE_CAPTION_SIDE_BSTART 0 // matches eLogicalSideBStart -#define NS_STYLE_CAPTION_SIDE_BEND 1 // matches eLogicalSideBEnd -#define NS_STYLE_CAPTION_SIDE_ISTART 2 // matches eLogicalSideIStart -#define NS_STYLE_CAPTION_SIDE_IEND 3 // matches eLogicalSideIEnd -#define NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE 4 -#define NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE 5 -#define NS_STYLE_CAPTION_SIDE_TOP 6 -#define NS_STYLE_CAPTION_SIDE_RIGHT 7 -#define NS_STYLE_CAPTION_SIDE_BOTTOM 8 -#define NS_STYLE_CAPTION_SIDE_LEFT 9 -#define NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE 10 -#define NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE 11 +// Constants for the caption-side property. Note that despite having "physical" +// names, these are actually interpreted according to the table's writing-mode: +// TOP and BOTTOM are treated as block-start and -end respectively, and LEFT +// and RIGHT are treated as line-left and -right. +#define NS_STYLE_CAPTION_SIDE_TOP 0 +#define NS_STYLE_CAPTION_SIDE_RIGHT 1 +#define NS_STYLE_CAPTION_SIDE_BOTTOM 2 +#define NS_STYLE_CAPTION_SIDE_LEFT 3 +#define NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE 4 +#define NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE 5 // constants for cell "scope" attribute #define NS_STYLE_CELL_SCOPE_ROW 0 diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index b3c4a25897..c647aa5fc3 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -24,6 +24,7 @@ #include "nsIDocument.h" #include "nsPrintfCString.h" #include "mozilla/Preferences.h" +#include "mozilla/ArenaObjectID.h" #ifdef DEBUG // #define NOISY_DEBUG @@ -308,18 +309,30 @@ nsStyleContext::MoveTo(nsStyleContext* aNewParent) // Assertions checking for visited style are just to avoid some tricky // cases we can't be bothered handling at the moment. MOZ_ASSERT(!IsStyleIfVisited()); + MOZ_ASSERT(!mParent->IsStyleIfVisited()); MOZ_ASSERT(!aNewParent->IsStyleIfVisited()); + MOZ_ASSERT(!mStyleIfVisited || mStyleIfVisited->mParent == mParent); nsStyleContext* oldParent = mParent; + if (oldParent->HasChildThatUsesResetStyle()) { + aNewParent->AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE); + } + aNewParent->AddRef(); - mParent->RemoveChild(this); - mParent = aNewParent; mParent->AddChild(this); - oldParent->Release(); + + if (mStyleIfVisited) { + oldParent = mStyleIfVisited->mParent; + aNewParent->AddRef(); + mStyleIfVisited->mParent->RemoveChild(mStyleIfVisited); + mStyleIfVisited->mParent = aNewParent; + mStyleIfVisited->mParent->AddChild(mStyleIfVisited); + oldParent->Release(); + } } already_AddRefed @@ -546,9 +559,28 @@ ShouldSuppressLineBreak(const nsStyleDisplay* aStyleDisplay, // the level containers themselves are breakable. We have to check // the container display type against all ruby display type here // because any of the ruby boxes could be anonymous. - if (aContainerDisplay->IsRubyDisplayType() && - aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER && - aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) { + // Note that, when certain HTML tags, e.g. form controls, have ruby + // level container display type, they could also escape from this flag + // while they shouldn't. However, it is generally fine since they + // won't usually break the assertion that there is no line break + // inside ruby, because: + // 1. their display types, the ruby level container types, are inline- + // outside, which means they won't cause any forced line break; and + // 2. they never start an inline span, which means their children, if + // any, won't be able to break the line its ruby ancestor lays; and + // 3. their parent frame is always a ruby content frame (due to + // anonymous ruby box generation), which makes line layout suppress + // any optional line break around this frame. + // However, there is one special case which is BR tag, because it + // directly affects the line layout. This case is handled by the BR + // frame which checks the flag of its parent frame instead of itself. + if ((aContainerDisplay->IsRubyDisplayType() && + aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER && + aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) || + // Since ruby base and ruby text may exist themselves without any + // non-anonymous frame outside, we should also check them. + aStyleDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE || + aStyleDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_TEXT) { return true; } return false; @@ -617,7 +649,14 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) // doesn't get confused by looking at the style data. if (!mParent) { uint8_t displayVal = disp->mDisplay; - nsRuleNode::EnsureBlockDisplay(displayVal, true); + if (displayVal != NS_STYLE_DISPLAY_CONTENTS) { + nsRuleNode::EnsureBlockDisplay(displayVal, true); + } else { + // http://dev.w3.org/csswg/css-display/#transformations + // "... a display-outside of 'contents' computes to block-level + // on the root element." + displayVal = NS_STYLE_DISPLAY_BLOCK; + } if (displayVal != disp->mDisplay) { nsStyleDisplay *mutable_display = static_cast(GetUniqueStyleData(eStyleStruct_Display)); @@ -733,6 +772,26 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) } } + /* + * According to https://drafts.csswg.org/css-writing-modes-3/#block-flow: + * + * If a box has a different block flow direction than its containing block: + * * If the box has a specified display of inline, its display computes + * to inline-block. [CSS21] + * ...etc. + */ + if (disp->mDisplay == NS_STYLE_DISPLAY_INLINE && mParent) { + // We don't need the full mozilla::WritingMode value (incorporating dir + // and text-orientation) here; just the writing-mode property is enough. + if (StyleVisibility()->mWritingMode != + mParent->StyleVisibility()->mWritingMode) { + nsStyleDisplay *mutable_display = + static_cast(GetUniqueStyleData(eStyleStruct_Display)); + mutable_display->mOriginalDisplay = mutable_display->mDisplay = + NS_STYLE_DISPLAY_INLINE_BLOCK; + } + } + // Compute User Interface style, to trigger loads of cursors StyleUserInterface(); } @@ -740,7 +799,8 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) nsChangeHint nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, nsChangeHint aParentHintsNotHandledForDescendants, - uint32_t* aEqualStructs) + uint32_t* aEqualStructs, + uint32_t* aSamePointerStructs) { PROFILER_LABEL("nsStyleContext", "CalcStyleDifference", js::ProfileEntry::Category::CSS); @@ -814,7 +874,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, differenceAlwaysHandledForDescendants) & \ aParentHintsNotHandledForDescendants)) { \ nsChangeHint difference = \ - this##struct_->CalcDifference(*other##struct_); \ + this##struct_->CalcDifference(*other##struct_ EXTRA_DIFF_ARGS); \ NS_ASSERTION(NS_IsHintSubset(difference, maxDifference), \ "CalcDifference() returned bigger hint than " \ "MaxDifference()"); \ @@ -826,7 +886,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, /* We still must call CalcDifference to see if there were any */ \ /* changes so that we can set *aEqualStructs appropriately. */ \ nsChangeHint difference = \ - this##struct_->CalcDifference(*other##struct_); \ + this##struct_->CalcDifference(*other##struct_ EXTRA_DIFF_ARGS); \ NS_ASSERTION(NS_IsHintSubset(difference, maxDifference), \ "CalcDifference() returned bigger hint than " \ "MaxDifference()"); \ @@ -845,6 +905,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, // smallest. This lets us skip later ones if we already have a hint // that subsumes their MaxDifference. (As the hints get // finer-grained, this optimization is becoming less useful, though.) +#define EXTRA_DIFF_ARGS /* nothing */ DO_STRUCT_DIFFERENCE(Display); DO_STRUCT_DIFFERENCE(XUL); DO_STRUCT_DIFFERENCE(Column); @@ -860,7 +921,11 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, DO_STRUCT_DIFFERENCE(Quotes); DO_STRUCT_DIFFERENCE(SVGReset); DO_STRUCT_DIFFERENCE(SVG); +#undef EXTRA_DIFF_ARGS +#define EXTRA_DIFF_ARGS , this DO_STRUCT_DIFFERENCE(Position); +#undef EXTRA_DIFF_ARGS +#define EXTRA_DIFF_ARGS /* nothing */ DO_STRUCT_DIFFERENCE(Font); DO_STRUCT_DIFFERENCE(Margin); DO_STRUCT_DIFFERENCE(Padding); @@ -868,12 +933,33 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, DO_STRUCT_DIFFERENCE(TextReset); DO_STRUCT_DIFFERENCE(Background); DO_STRUCT_DIFFERENCE(Color); +#undef EXTRA_DIFF_ARGS #undef DO_STRUCT_DIFFERENCE MOZ_ASSERT(styleStructCount == nsStyleStructID_Length, "missing a call to DO_STRUCT_DIFFERENCE"); + // We check for struct pointer equality here rather than as part of the + // DO_STRUCT_DIFFERENCE calls, since those calls can result in structs + // we previously examined and found to be null on this style context + // getting computed by later DO_STRUCT_DIFFERENCE calls (which can + // happen when the nsRuleNode::ComputeXXXData method looks up another + // struct.) This is important for callers in RestyleManager that + // need to know the equality or not of the final set of cached struct + // pointers. + *aSamePointerStructs = 0; + +#define STYLE_STRUCT(name_, callback_) \ + { \ + const nsStyle##name_* data = PeekStyle##name_(); \ + if (!data || data == aOther->Style##name_()) { \ + *aSamePointerStructs |= NS_STYLE_INHERIT_BIT(name_); \ + } \ + } +#include "nsStyleStructList.h" +#undef STYLE_STRUCT + // Note that we do not check whether this->RelevantLinkVisited() != // aOther->RelevantLinkVisited(); we don't need to since // nsCSSFrameConstructor::DoContentStateChanged always adds @@ -1089,7 +1175,8 @@ void* nsStyleContext::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW { // Check the recycle list first. - return aPresContext->PresShell()->AllocateByObjectID(nsPresArena::nsStyleContext_id, sz); + return aPresContext->PresShell()-> + AllocateByObjectID(eArenaObjectID_nsStyleContext, sz); } // Overridden to prevent the global delete from being called, since the memory @@ -1105,7 +1192,8 @@ nsStyleContext::Destroy() // Don't let the memory be freed, since it will be recycled // instead. Don't call the global operator delete. - presContext->PresShell()->FreeByObjectID(nsPresArena::nsStyleContext_id, this); + presContext->PresShell()-> + FreeByObjectID(eArenaObjectID_nsStyleContext, this); } already_AddRefed @@ -1122,6 +1210,12 @@ NS_NewStyleContext(nsStyleContext* aParentContext, return context.forget(); } +nsIPresShell* +nsStyleContext::Arena() +{ + return mRuleNode->PresContext()->PresShell(); +} + static inline void ExtractAnimationValue(nsCSSProperty aProperty, nsStyleContext* aStyleContext, @@ -1259,13 +1353,6 @@ nsStyleContext::LookupStruct(const nsACString& aName, nsStyleStructID& aResult) } #endif -bool -nsStyleContext::HasSameCachedStyleData(nsStyleContext* aOther, - nsStyleStructID aSID) -{ - return GetCachedStyleData(aSID) == aOther->GetCachedStyleData(aSID); -} - void nsStyleContext::SwapStyleData(nsStyleContext* aNewContext, uint32_t aStructs) { diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index a687a8dbe8..d25fc32ec8 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -73,6 +73,13 @@ public: void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW; void Destroy(); + // These two methods are for use by ArenaRefPtr. + static mozilla::ArenaObjectID ArenaObjectID() + { + return mozilla::eArenaObjectID_nsStyleContext; + } + nsIPresShell* Arena(); + #ifdef DEBUG /** * Initializes a cached pref, which is only used in DEBUG code. @@ -173,6 +180,9 @@ public: bool HasPseudoElementData() const { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); } + bool HasChildThatUsesResetStyle() const + { return mBits & NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE; } + // Is the only link whose visitedness is allowed to influence the // style of the node this style context is for (which is that element // or its nearest ancestor that is a link) visited? @@ -271,12 +281,6 @@ public: #undef STYLE_STRUCT_RESET #undef STYLE_STRUCT_INHERITED - /** - * Returns whether this style context and aOther both have the same - * cached style struct pointer for a given style struct. - */ - bool HasSameCachedStyleData(nsStyleContext* aOther, nsStyleStructID aSID); - /** * Returns whether this style context has cached, inherited style data for a * given style struct. @@ -360,7 +364,8 @@ public: */ nsChangeHint CalcStyleDifference(nsStyleContext* aOther, nsChangeHint aParentHintsNotHandledForDescendants, - uint32_t* aEqualStructs); + uint32_t* aEqualStructs, + uint32_t* aSamePointerStructs); /** * Get a color that depends on link-visitedness using this and diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index a923d78734..0955e626bd 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -260,6 +260,10 @@ nsStyleSet::BeginReconstruct() NS_ASSERTION(!mInReconstruct, "Unmatched begin/end?"); NS_ASSERTION(mRuleTree, "Reconstructing before first construction?"); + // Clear any ArenaRefPtr-managed style contexts, as we don't want them + // held on to after the rule tree has been reconstructed. + PresContext()->PresShell()->ClearArenaRefPtrs(eArenaObjectID_nsStyleContext); + // Create a new rule tree root nsRuleNode* newTree = nsRuleNode::CreateRootNode(mRuleTree->PresContext()); @@ -385,6 +389,14 @@ SortStyleSheetsByScope(nsTArray& aSheets) nsresult nsStyleSet::GatherRuleProcessors(sheetType aType) { + // We might be in GatherRuleProcessors because we are dropping a sheet, + // resulting in an nsCSSSelector being destroyed. Tell the + // RestyleManager for each document we're used in so that they can + // drop any nsCSSSelector pointers (used for eRestyle_SomeDescendants) + // in their mPendingRestyles. + if (IsCSSSheetType(aType)) { + ClearSelectors(); + } nsCOMPtr oldRuleProcessor(mRuleProcessors[aType]); nsTArray> oldScopedDocRuleProcessors; if (aType == eAgentSheet || aType == eUserSheet) { @@ -845,6 +857,7 @@ ReplaceAnimationRule(nsRuleNode *aOldRuleNode, if (aNewAnimRule) { n = n->Transition(aNewAnimRule, nsStyleSet::eAnimationSheet, false); + n->SetIsAnimationRule(); } for (uint32_t i = moreSpecificNodes.Length(); i-- != 0; ) { @@ -1439,6 +1452,7 @@ struct RuleNodeInfo { nsIStyleRule* mRule; uint8_t mLevel; bool mIsImportant; + bool mIsAnimationRule; }; struct CascadeLevel { @@ -1508,6 +1522,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, curRule->mRule = ruleNode->GetRule(); curRule->mLevel = ruleNode->GetLevel(); curRule->mIsImportant = ruleNode->IsImportantRule(); + curRule->mIsAnimationRule = ruleNode->IsAnimationRule(); } nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); @@ -1538,6 +1553,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, GetAnimationRule(aElement, aPseudoType); if (rule) { ruleWalker.ForwardOnPossiblyCSSRule(rule); + ruleWalker.CurrentNode()->SetIsAnimationRule(); } } break; @@ -1550,6 +1566,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, GetAnimationRule(aElement, aPseudoType); if (rule) { ruleWalker.ForwardOnPossiblyCSSRule(rule); + ruleWalker.CurrentNode()->SetIsAnimationRule(); } } break; @@ -1615,6 +1632,9 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, if (!doReplace) { ruleWalker.ForwardOnPossiblyCSSRule(ruleInfo.mRule); + if (ruleInfo.mIsAnimationRule) { + ruleWalker.CurrentNode()->SetIsAnimationRule(); + } } } } @@ -2369,14 +2389,16 @@ struct MOZ_STACK_CLASS AttributeData : public AttributeRuleProcessorData { aAttrHasChanged, aOtherValue, aTreeMatchContext), mHint(nsRestyleHint(0)) {} - nsRestyleHint mHint; + nsRestyleHint mHint; + RestyleHintData mHintData; }; static bool SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { AttributeData* data = (AttributeData*)aData; - nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data); + nsRestyleHint hint = + aProcessor->HasAttributeDependentStyle(data, data->mHintData); data->mHint = nsRestyleHint(data->mHint | hint); return true; // continue } @@ -2387,7 +2409,9 @@ nsStyleSet::HasAttributeDependentStyle(Element* aElement, nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, - const nsAttrValue* aOtherValue) + const nsAttrValue* aOtherValue, + mozilla::RestyleHintData& + aRestyleHintDataResult) { TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, aElement->OwnerDoc()); @@ -2395,6 +2419,11 @@ nsStyleSet::HasAttributeDependentStyle(Element* aElement, AttributeData data(PresContext(), aElement, aAttribute, aModType, aAttrHasChanged, aOtherValue, treeContext); WalkRuleProcessors(SheetHasAttributeStyle, &data, false); + if (!(data.mHint & eRestyle_Subtree)) { + // No point keeping the list of selectors around if we are going to + // restyle the whole subtree unconditionally. + aRestyleHintDataResult = Move(data.mHintData); + } return data.mHint; } @@ -2481,3 +2510,13 @@ nsStyleSet::HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType) static_cast(mRuleProcessors[aSheetType].get()); return rp->IsUsedByMultipleStyleSets(); } + +void +nsStyleSet::ClearSelectors() +{ + // We might be called before we've done our first rule tree construction. + if (!mRuleTree) { + return; + } + PresContext()->RestyleManager()->ClearSelectors(); +} diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index e807af8e03..ff041525f1 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -286,7 +286,9 @@ class nsStyleSet final nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, - const nsAttrValue* aOtherValue); + const nsAttrValue* aOtherValue, + mozilla::RestyleHintData& + aRestyleHintDataResult); /* * Do any processing that needs to happen as a result of a change in @@ -345,6 +347,12 @@ class nsStyleSet final return mSheets[aType].ObjectAt(aIndex); } + void AppendAllXBLStyleSheets(nsTArray& aArray) const { + if (mBindingManager) { + mBindingManager->AppendAllSheets(aArray); + } + } + nsresult RemoveDocStyleSheet(nsIStyleSheet* aSheet); nsresult AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument); @@ -397,6 +405,10 @@ class nsStyleSet final bool HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType); + // Tells the RestyleManager for the document using this style set + // to drop any nsCSSSelector pointers it has. + void ClearSelectors(); + private: nsStyleSet(const nsStyleSet& aCopy) = delete; nsStyleSet& operator=(const nsStyleSet& aCopy) = delete; diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 155017ee97..77bf83bfac 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -167,7 +167,7 @@ void nsStyleFont::Destroy(nsPresContext* aContext) { this->~nsStyleFont(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleFont_id, this); + FreeByObjectID(eArenaObjectID_nsStyleFont, this); } void @@ -256,7 +256,7 @@ nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& if ((aFont1.decorations == aFont2.decorations)) { return NS_STYLE_HINT_NONE; } - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } return NS_STYLE_HINT_REFLOW; } @@ -310,7 +310,7 @@ void nsStyleMargin::Destroy(nsPresContext* aContext) { this->~nsStyleMargin(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleMargin_id, this); + FreeByObjectID(eArenaObjectID_nsStyleMargin, this); } @@ -333,8 +333,9 @@ nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const } // Margin differences can't affect descendant intrinsic sizes and // don't need to force children to reflow. - return NS_CombineHint(nsChangeHint_NeedReflow, - nsChangeHint_ClearAncestorIntrinsics); + return nsChangeHint_NeedReflow | + nsChangeHint_ReflowChangesSizeOrPosition | + nsChangeHint_ClearAncestorIntrinsics; } nsStylePadding::nsStylePadding() @@ -360,7 +361,7 @@ void nsStylePadding::Destroy(nsPresContext* aContext) { this->~nsStylePadding(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStylePadding_id, this); + FreeByObjectID(eArenaObjectID_nsStylePadding, this); } void nsStylePadding::RecalcData() @@ -512,7 +513,7 @@ nsStyleBorder::Destroy(nsPresContext* aContext) { UntrackImage(aContext); this->~nsStyleBorder(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleBorder_id, this); + FreeByObjectID(eArenaObjectID_nsStyleBorder, this); } nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const @@ -538,28 +539,28 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const // See the explanation in nsChangeHint.h of // nsChangeHint_BorderStyleNoneChange . // Furthermore, even though we know *this* side is 0 width, just - // assume a visual hint for some other change rather than bother + // assume a repaint hint for some other change rather than bother // tracking this result through the rest of the function. if (HasVisibleStyle(ix) != aOther.HasVisibleStyle(ix)) { - return NS_CombineHint(NS_STYLE_HINT_VISUAL, + return NS_CombineHint(nsChangeHint_RepaintFrame, nsChangeHint_BorderStyleNoneChange); } } // Note that mBorderStyle stores not only the border style but also // color-related flags. Given that we've already done an mComputedBorder - // comparison, border-style differences can only lead to a VISUAL hint. So + // comparison, border-style differences can only lead to a repaint hint. So // it's OK to just compare the values directly -- if either the actual // style or the color flags differ we want to repaint. NS_FOR_CSS_SIDES(ix) { if (mBorderStyle[ix] != aOther.mBorderStyle[ix] || mBorderColor[ix] != aOther.mBorderColor[ix]) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } if (mBorderRadius != aOther.mBorderRadius || !mBorderColors != !aOther.mBorderColors) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) { if (mBorderImageSource != aOther.mBorderImageSource || @@ -569,7 +570,7 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const mBorderImageFill != aOther.mBorderImageFill || mBorderImageWidth != aOther.mBorderImageWidth || mBorderImageOutset != aOther.mBorderImageOutset) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } // Note that at this point if mBorderColors is non-null so is @@ -578,7 +579,7 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const NS_FOR_CSS_SIDES(ix) { if (!nsBorderColors::Equal(mBorderColors[ix], aOther.mBorderColors[ix])) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } } @@ -1119,6 +1120,8 @@ nsStyleClipPath::ReleaseRef() NS_ASSERTION(mURL, "expected pointer"); mURL->Release(); } + // mBasicShap, mURL, etc. are all pointers in a union of pointers. Nulling + // one of them nulls all of them: mURL = nullptr; } @@ -1496,7 +1499,9 @@ IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2) return true; } -nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const +nsChangeHint +nsStylePosition::CalcDifference(const nsStylePosition& aOther, + nsStyleContext* aContext) const { nsChangeHint hint = nsChangeHint(0); @@ -1582,35 +1587,31 @@ nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) cons NS_UpdateHint(hint, nsChangeHint_NeedReflow); } - // Properties that apply only to multi-line flex containers: - // 'align-content' can change the positioning & sizing of a multi-line flex - // container's children when there's extra space in the cross axis, but it - // shouldn't affect the container's own sizing. - // - // NOTE: If we get here, we know that mFlexWrap == aOther.mFlexWrap - // (otherwise, we would've returned earlier). So it doesn't matter which one - // of those we check to see if we're multi-line. - if (mFlexWrap != NS_STYLE_FLEX_WRAP_NOWRAP && - mAlignContent != aOther.mAlignContent) { + // 'align-content' doesn't apply to a single-line flexbox but we don't know + // if we're a flex container at this point so we can't optimize for that. + if (mAlignContent != aOther.mAlignContent) { NS_UpdateHint(hint, nsChangeHint_NeedReflow); } - if (mHeight != aOther.mHeight || - mMinHeight != aOther.mMinHeight || - mMaxHeight != aOther.mMaxHeight) { - // Height changes can affect descendant intrinsic sizes due to replaced - // elements with percentage heights in descendants which also have - // percentage heights. This is handled via nsChangeHint_UpdateComputedBSize + bool widthChanged = mWidth != aOther.mWidth || + mMinWidth != aOther.mMinWidth || + mMaxWidth != aOther.mMaxWidth; + bool heightChanged = mHeight != aOther.mHeight || + mMinHeight != aOther.mMinHeight || + mMaxHeight != aOther.mMaxHeight; + bool isVertical = WritingMode(aContext).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. NS_UpdateHint(hint, nsChangeHint_NeedReflow | nsChangeHint_UpdateComputedBSize | nsChangeHint_ReflowChangesSizeOrPosition); } - if (mWidth != aOther.mWidth || - mMinWidth != aOther.mMinWidth || - mMaxWidth != aOther.mMaxWidth) { - // None of our width differences can affect descendant intrinsic + 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. NS_UpdateHint(hint, NS_SubtractHint(nsChangeHint_AllReflowHints, NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics, @@ -1703,7 +1704,7 @@ nsStyleTableBorder::nsStyleTableBorder() mBorderCollapse = NS_STYLE_BORDER_SEPARATE; mEmptyCells = NS_STYLE_TABLE_EMPTY_CELLS_SHOW; - mCaptionSide = NS_STYLE_CAPTION_SIDE_BSTART; + mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP; mBorderSpacingCol = 0; mBorderSpacingRow = 0; } @@ -1764,7 +1765,7 @@ nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const { if (mColor == aOther.mColor) return NS_STYLE_HINT_NONE; - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } // -------------------- @@ -2234,7 +2235,7 @@ nsStyleBackground::Destroy(nsPresContext* aContext) this->~nsStyleBackground(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleBackground_id, this); + FreeByObjectID(eArenaObjectID_nsStyleBackground, this); } nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const @@ -2251,18 +2252,20 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) { if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) || (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)) - return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); + return NS_CombineHint(nsChangeHint_UpdateEffects, + nsChangeHint_RepaintFrame); hasVisualDifference = true; } } else { if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) - return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); + return NS_CombineHint(nsChangeHint_UpdateEffects, + nsChangeHint_RepaintFrame); hasVisualDifference = true; } } if (hasVisualDifference || mBackgroundColor != aOther.mBackgroundColor) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; if (mAttachmentCount != aOther.mAttachmentCount || mClipCount != aOther.mClipCount || @@ -2820,7 +2823,7 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const // We do not need to apply nsChangeHint_UpdateTransformLayer since // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and // ensure layers are rebuilt (or removed). - NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AddOrRemoveTransform, + NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateContainingBlock, NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame))); } else { @@ -2853,7 +2856,8 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame); for (uint8_t index = 0; index < 3; ++index) if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) { - NS_UpdateHint(transformHint, kUpdateOverflowAndRepaintHint); + NS_UpdateHint(transformHint, NS_CombineHint(nsChangeHint_UpdateTransformLayer, + nsChangeHint_UpdatePostTransformOverflow)); break; } @@ -2863,6 +2867,11 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const break; } + if (HasPerspectiveStyle() != aOther.HasPerspectiveStyle()) { + // A change from/to being a containing block for position:fixed. + NS_UpdateHint(hint, nsChangeHint_UpdateContainingBlock); + } + if (mChildPerspective != aOther.mChildPerspective || mTransformStyle != aOther.mTransformStyle || mTransformBox != aOther.mTransformBox) @@ -2970,6 +2979,9 @@ nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) nsChangeHint hint = nsChangeHint(0); if (mDirection != aOther.mDirection || mWritingMode != aOther.mWritingMode) { + // It's important that a change in mWritingMode results in frame + // reconstruction, because it may affect intrinsic size (see + // nsSubDocumentFrame::GetIntrinsicISize/BSize). NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); } else { if ((mImageOrientation != aOther.mImageOrientation)) { @@ -3138,7 +3150,7 @@ nsStyleContent::Destroy(nsPresContext* aContext) this->~nsStyleContent(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleContent_id, this); + FreeByObjectID(eArenaObjectID_nsStyleContent, this); } nsStyleContent::nsStyleContent(const nsStyleContent& aSource) @@ -3354,10 +3366,12 @@ nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) co uint8_t otherLineStyle = aOther.GetDecorationStyle(); if (mTextDecorationLine != aOther.mTextDecorationLine || lineStyle != otherLineStyle) { - // Repaint for other style decoration lines because they must be in - // default overflow rect - nsChangeHint hint = NS_STYLE_HINT_VISUAL; + // Changes to our text-decoration line can impact our overflow area & + // also our descendants' overflow areas (particularly for text-frame + // descendants). So, we update those areas & trigger a repaint. + nsChangeHint hint = nsChangeHint_RepaintFrame; NS_UpdateHint(hint, nsChangeHint_UpdateSubtreeOverflow); + NS_UpdateHint(hint, nsChangeHint_SchedulePaint); return hint; } @@ -3367,11 +3381,11 @@ nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) co GetDecorationColor(decColor, isFG); aOther.GetDecorationColor(otherDecColor, otherIsFG); if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } if (mTextOverflow != aOther.mTextOverflow) { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } return NS_STYLE_HINT_NONE; } @@ -3419,7 +3433,7 @@ nsStyleText::nsStyleText(void) mRubyPosition = NS_STYLE_RUBY_POSITION_OVER; mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO; mTextCombineUpright = NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE; - mControlCharacterVisibility = NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN; + mControlCharacterVisibility = NS_STYLE_CONTROL_CHARACTER_VISIBILITY_VISIBLE; mLetterSpacing.SetNormalValue(); mLineHeight.SetNormalValue(); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 6f40b656f1..3875ec99c2 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -11,6 +11,7 @@ #ifndef nsStyleStruct_h___ #define nsStyleStruct_h___ +#include "mozilla/ArenaObjectID.h" #include "mozilla/Attributes.h" #include "mozilla/CSSVariableValues.h" #include "nsColor.h" @@ -30,9 +31,9 @@ #include "CounterStyleManager.h" class nsIFrame; -class nsTextFrame; class nsIURI; class nsStyleContext; +class nsTextFrame; class imgIContainer; // Includes nsStyleStructID. @@ -42,6 +43,14 @@ class imgIContainer; // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h #define NS_STYLE_INHERIT_MASK 0x000ffffff +// Bits for inherited structs. +#define NS_STYLE_INHERITED_STRUCT_MASK \ + ((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1) +// Bits for reset structs. +#define NS_STYLE_RESET_STRUCT_MASK \ + (((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \ + << nsStyleStructID_Inherited_Count) + // Additional bits for nsStyleContext's mBits: // See nsStyleContext::HasTextDecorationLines #define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000 @@ -64,16 +73,22 @@ class imgIContainer; #define NS_STYLE_IN_DISPLAY_NONE_SUBTREE 0x100000000 // See nsStyleContext::FindChildWithRules #define NS_STYLE_INELIGIBLE_FOR_SHARING 0x200000000 +// See nsStyleContext::HasChildThatUsesResetStyle +#define NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE 0x400000000 // See nsStyleContext::GetPseudoEnum -#define NS_STYLE_CONTEXT_TYPE_SHIFT 34 +#define NS_STYLE_CONTEXT_TYPE_SHIFT 35 // Additional bits for nsRuleNode's mDependentBits: +#define NS_RULE_NODE_IS_ANIMATION_RULE 0x01000000 #define NS_RULE_NODE_GC_MARK 0x02000000 #define NS_RULE_NODE_USED_DIRECTLY 0x04000000 #define NS_RULE_NODE_IS_IMPORTANT 0x08000000 #define NS_RULE_NODE_LEVEL_MASK 0xf0000000 #define NS_RULE_NODE_LEVEL_SHIFT 28 +// Additional bits for nsRuleNode's mNoneBits: +#define NS_RULE_NODE_HAS_ANIMATION_DATA 0x80000000 + // The lifetime of these objects is managed by the presshell's arena. struct nsStyleFont { @@ -106,7 +121,7 @@ public: void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleFont_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleFont, sz); } void Destroy(nsPresContext* aContext); @@ -338,7 +353,7 @@ struct nsStyleColor { nsChangeHint CalcDifference(const nsStyleColor& aOther) const; static nsChangeHint MaxDifference() { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } static nsChangeHint DifferenceAlwaysHandledForDescendants() { // CalcDifference never returns the reflow hints that are sometimes @@ -348,12 +363,12 @@ struct nsStyleColor { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleColor_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColor, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleColor(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleColor_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleColor, this); } // Don't add ANY members to this struct! We can achieve caching in the rule @@ -368,14 +383,14 @@ struct nsStyleBackground { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleBackground_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz); } void Destroy(nsPresContext* aContext); nsChangeHint CalcDifference(const nsStyleBackground& aOther) const; static nsChangeHint MaxDifference() { return NS_CombineHint(nsChangeHint_UpdateEffects, - NS_CombineHint(NS_STYLE_HINT_VISUAL, + NS_CombineHint(nsChangeHint_RepaintFrame, nsChangeHint_NeutralChange)); } static nsChangeHint DifferenceAlwaysHandledForDescendants() { @@ -473,12 +488,12 @@ struct nsStyleBackground { return !(*this == aOther); } }; - + struct Repeat; friend struct Repeat; struct Repeat { uint8_t mXRepeat, mYRepeat; - + // Initialize nothing Repeat() {} @@ -603,19 +618,20 @@ struct nsStyleMargin { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleMargin_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz); } void Destroy(nsPresContext* aContext); void RecalcData(); nsChangeHint CalcDifference(const nsStyleMargin& aOther) const; static nsChangeHint MaxDifference() { - return NS_CombineHint(nsChangeHint_NeedReflow, - nsChangeHint_ClearAncestorIntrinsics); + return nsChangeHint_NeedReflow | + nsChangeHint_ReflowChangesSizeOrPosition | + nsChangeHint_ClearAncestorIntrinsics; } static nsChangeHint DifferenceAlwaysHandledForDescendants() { - // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and - // nsChangeHint_NeedReflow as hints not handled for descendants. + // CalcDifference can return all of the reflow hints sometimes not + // handled for descendants as hints not handled for descendants. return nsChangeHint(0); } @@ -646,7 +662,7 @@ struct nsStylePadding { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStylePadding_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz); } void Destroy(nsPresContext* aContext); @@ -657,8 +673,14 @@ struct nsStylePadding { nsChangeHint_ClearDescendantIntrinsics); } static nsChangeHint DifferenceAlwaysHandledForDescendants() { - // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as an - // hint not handled for descendants. + // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as + // a hint not handled for descendants. We could (and perhaps + // should) return nsChangeHint_NeedReflow and + // nsChangeHint_ReflowChangesSizeOrPosition as always handled for + // descendants, but since they're always returned in conjunction + // with nsChangeHint_ClearAncestorIntrinsics (which is not), it + // won't ever lead to any optimization in + // nsStyleContext::CalcStyleDifference. return nsChangeHint(0); } @@ -809,13 +831,10 @@ public: nsCSSShadowItem mArray[1]; // This MUST be the last item }; -// 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. +// 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. #define NS_ROUND_BORDER_TO_PIXELS(l,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. @@ -839,7 +858,7 @@ struct nsStyleBorder { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleBorder_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz); } void Destroy(nsPresContext* aContext); @@ -1069,12 +1088,12 @@ struct nsStyleOutline { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleOutline_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleOutline(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleOutline_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleOutline, this); } void RecalcData(nsPresContext* aContext); @@ -1165,12 +1184,12 @@ struct nsStyleList { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleList_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleList(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleList_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleList, this); } nsChangeHint CalcDifference(const nsStyleList& aOther) const; @@ -1266,7 +1285,8 @@ struct nsStyleGridTemplate { } inline bool operator!=(const nsStyleGridTemplate& aOther) const { - return mLineNameLists != aOther.mLineNameLists || + return mIsSubgrid != aOther.mIsSubgrid || + mLineNameLists != aOther.mLineNameLists || mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions || mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions; } @@ -1396,12 +1416,12 @@ struct nsStyleTextReset { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleTextReset_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleTextReset(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleTextReset_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, this); } uint8_t GetDecorationStyle() const @@ -1473,12 +1493,12 @@ struct nsStyleText { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleText_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleText(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleText_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleText, this); } nsChangeHint CalcDifference(const nsStyleText& aOther) const; @@ -1665,12 +1685,12 @@ struct nsStyleVisibility { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleVisibility_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleVisibility(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleVisibility_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, this); } nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const; @@ -1894,12 +1914,12 @@ struct nsStyleDisplay { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleDisplay_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleDisplay(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleDisplay_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, this); } nsChangeHint CalcDifference(const nsStyleDisplay& aOther) const; @@ -1910,7 +1930,7 @@ struct nsStyleDisplay { nsChangeHint_UpdateTransformLayer | nsChangeHint_UpdateOverflow | nsChangeHint_UpdatePostTransformOverflow | - nsChangeHint_AddOrRemoveTransform | + nsChangeHint_UpdateContainingBlock | nsChangeHint_NeutralChange); } static nsChangeHint DifferenceAlwaysHandledForDescendants() { @@ -1978,7 +1998,7 @@ struct nsStyleDisplay { uint8_t mTransformBox; // [reset] see nsStyleConsts.h nsRefPtr mSpecifiedTransform; // [reset] nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only - nsStyleCoord mChildPerspective; // [reset] coord + nsStyleCoord mChildPerspective; // [reset] none, coord nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc nsAutoTArray mTransitions; // [reset] @@ -2159,12 +2179,12 @@ struct nsStyleTable { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleTable_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleTable(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleTable_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleTable, this); } nsChangeHint CalcDifference(const nsStyleTable& aOther) const; @@ -2190,15 +2210,16 @@ struct nsStylePosition { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStylePosition_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz); } void Destroy(nsPresContext* aContext) { this->~nsStylePosition(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStylePosition_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStylePosition, this); } - nsChangeHint CalcDifference(const nsStylePosition& aOther) const; + nsChangeHint CalcDifference(const nsStylePosition& aOther, + nsStyleContext* aContext) const; static nsChangeHint MaxDifference() { return NS_CombineHint(NS_STYLE_HINT_REFLOW, nsChangeHint(nsChangeHint_RecomputePosition | @@ -2348,12 +2369,12 @@ struct nsStyleTableBorder { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleTableBorder_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleTableBorder(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleTableBorder_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, this); } nsChangeHint CalcDifference(const nsStyleTableBorder& aOther) const; @@ -2368,11 +2389,6 @@ struct nsStyleTableBorder { nsChangeHint_ClearAncestorIntrinsics; } - // Return the mCaptionSide value, with physical values resolved to - // the appropriate logical value for the given writing mode. - // (The definition of this is in WritingModes.h.) - inline uint8_t LogicalCaptionSide(mozilla::WritingMode aWM) const; - nscoord mBorderSpacingCol;// [inherited] nscoord mBorderSpacingRow;// [inherited] uint8_t mBorderCollapse;// [inherited] @@ -2449,12 +2465,12 @@ struct nsStyleQuotes { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleQuotes_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleQuotes, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleQuotes(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleQuotes_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleQuotes, this); } void SetInitial(); @@ -2531,7 +2547,7 @@ struct nsStyleContent { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleContent_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz); } void Destroy(nsPresContext* aContext); @@ -2640,12 +2656,12 @@ struct nsStyleUIReset { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleUIReset_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleUIReset(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleUIReset_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, this); } nsChangeHint CalcDifference(const nsStyleUIReset& aOther) const; @@ -2702,12 +2718,12 @@ struct nsStyleUserInterface { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleUserInterface_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleUserInterface(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleUserInterface_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, this); } nsChangeHint CalcDifference(const nsStyleUserInterface& aOther) const; @@ -2749,12 +2765,12 @@ struct nsStyleXUL { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleXUL_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleXUL(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleXUL_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleXUL, this); } nsChangeHint CalcDifference(const nsStyleXUL& aOther) const; @@ -2785,12 +2801,12 @@ struct nsStyleColumn { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleColumn_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleColumn(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleColumn_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleColumn, this); } nsChangeHint CalcDifference(const nsStyleColumn& aOther) const; @@ -2878,12 +2894,12 @@ struct nsStyleSVG { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleSVG_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleSVG(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleSVG_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVG, this); } nsChangeHint CalcDifference(const nsStyleSVG& aOther) const; @@ -3160,12 +3176,12 @@ struct nsStyleSVGReset { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleSVGReset_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleSVGReset(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleSVGReset_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this); } nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const; @@ -3182,7 +3198,7 @@ struct nsStyleSVGReset { } bool HasFilters() const { - return mFilters.Length() > 0; + return !mFilters.IsEmpty(); } bool HasNonScalingStroke() const { @@ -3211,12 +3227,12 @@ struct nsStyleVariables { void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->PresShell()-> - AllocateByObjectID(nsPresArena::nsStyleVariables_id, sz); + AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz); } void Destroy(nsPresContext* aContext) { this->~nsStyleVariables(); aContext->PresShell()-> - FreeByObjectID(nsPresArena::nsStyleVariables_id, this); + FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this); } nsChangeHint CalcDifference(const nsStyleVariables& aOther) const; diff --git a/layout/style/nsStyleStructFwd.h b/layout/style/nsStyleStructFwd.h index 4ed02b79e3..c9e7a68914 100644 --- a/layout/style/nsStyleStructFwd.h +++ b/layout/style/nsStyleStructFwd.h @@ -65,4 +65,6 @@ eStyleStruct_BackendOnly = nsStyleStructID_Length // A bit corresponding to each struct ID #define NS_STYLE_INHERIT_BIT(sid_) (1 << uint64_t(eStyleStruct_##sid_)) +typedef decltype(nsStyleStructID(0) + nsStyleStructID(0)) nsStyleStructID_size_t; + #endif /* nsStyleStructFwd_h_ */ diff --git a/layout/style/nsStyleStructInlines.h b/layout/style/nsStyleStructInlines.h index 3883d7ceb1..e2da9c5d58 100644 --- a/layout/style/nsStyleStructInlines.h +++ b/layout/style/nsStyleStructInlines.h @@ -138,8 +138,10 @@ nsStyleDisplay::HasTransform(const nsIFrame* aContextFrame) const bool nsStyleDisplay::IsFixedPosContainingBlock(const nsIFrame* aContextFrame) const { + NS_ASSERTION(aContextFrame->StyleDisplay() == this, + "unexpected aContextFrame"); return (HasTransform(aContextFrame) || HasPerspectiveStyle() || - !aContextFrame->StyleSVGReset()->mFilters.IsEmpty()) && + aContextFrame->StyleSVGReset()->HasFilters()) && !aContextFrame->IsSVGText(); } diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 8d88b643a0..6aed36a953 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -116,6 +116,7 @@ support-files = file_bug1055933_circle-xxl.png [test_bug1089417.html] support-files = file_bug1089417_iframe.html [test_bug1112014.html] +[test_bug1203766.html] [test_cascade.html] [test_ch_ex_no_infloops.html] [test_compute_data_with_start_struct.html] diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index b44b07bcb0..b7064f3f91 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2365,8 +2365,8 @@ var gCSSProperties = { domProp: "captionSide", inherited: true, type: CSS_TYPE_LONGHAND, - initial_values: [ "block-start" ], - other_values: [ "block-end", "inline-start", "inline-end", "block-start-outside", "block-end-outside", "top", "bottom", "left", "right", "top-outside", "bottom-outside" ], + initial_values: [ "top" ], + other_values: [ "bottom", "left", "right", "top-outside", "bottom-outside" ], invalid_values: [] }, "clear": { diff --git a/layout/style/test/test_bug1203766.html b/layout/style/test/test_bug1203766.html new file mode 100644 index 0000000000..5d8152440b --- /dev/null +++ b/layout/style/test/test_bug1203766.html @@ -0,0 +1,112 @@ + + +Test for bug 1203766 + + + +Mozilla Bug 1203766 +

+
+
+
+
+
diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index e72f397a8d..882fdd774c 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -156,7 +156,7 @@ nsTableOuterFrame::RemoveFrame(ChildListID aListID, // The inner frame can't be removed so this should be the caption NS_PRECONDITION(kCaptionList == aListID, "can't remove inner frame"); - if (HasSideCaption(GetWritingMode())) { + if (HasSideCaption()) { // The old caption isize had an effect on the inner table isize, so // we're going to need to reflow it. Mark it dirty InnerTableFrame()->AddStateBits(NS_FRAME_IS_DIRTY); @@ -307,7 +307,7 @@ nsTableOuterFrame::GetMinISize(nsRenderingContext *aRenderingContext) nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mCaptionFrames.FirstChild(), nsLayoutUtils::MIN_ISIZE); - if (HasSideCaption(GetWritingMode())) { + if (HasSideCaption()) { iSize += capISize; } else { if (capISize > iSize) { @@ -326,12 +326,11 @@ nsTableOuterFrame::GetPrefISize(nsRenderingContext *aRenderingContext) maxISize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, InnerTableFrame(), nsLayoutUtils::PREF_ISIZE); - WritingMode wm = GetWritingMode(); if (mCaptionFrames.NotEmpty()) { - uint8_t captionSide = GetLogicalCaptionSide(wm); + uint8_t captionSide = GetCaptionSide(); switch (captionSide) { - case NS_STYLE_CAPTION_SIDE_ISTART: - case NS_STYLE_CAPTION_SIDE_IEND: + case NS_STYLE_CAPTION_SIDE_LEFT: + case NS_STYLE_CAPTION_SIDE_RIGHT: { nscoord capMin = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, @@ -343,14 +342,14 @@ nsTableOuterFrame::GetPrefISize(nsRenderingContext *aRenderingContext) default: { nsLayoutUtils::IntrinsicISizeType iwt; - if (captionSide == NS_STYLE_CAPTION_SIDE_BSTART || - captionSide == NS_STYLE_CAPTION_SIDE_BEND) { + if (captionSide == NS_STYLE_CAPTION_SIDE_TOP || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // Don't let the caption's pref isize expand the table's pref // isize. iwt = nsLayoutUtils::MIN_ISIZE; } else { - NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE || - captionSide == NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE, + NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE, "unexpected caption side"); iwt = nsLayoutUtils::PREF_ISIZE; } @@ -420,13 +419,13 @@ nsTableOuterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, // GetPrefISize. See bug 349457 for an example. // Match the availableISize logic in Reflow. - uint8_t captionSide = GetLogicalCaptionSide(aWM); + uint8_t captionSide = GetCaptionSide(); nscoord inlineSize; if (captionSide == NO_SIDE) { inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM, aCBSize, kidAvailableISize); - } else if (captionSide == NS_STYLE_CAPTION_SIDE_ISTART || - captionSide == NS_STYLE_CAPTION_SIDE_IEND) { + } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT || + captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) { nscoord capISize = ChildShrinkWrapISize(aRenderingContext, mCaptionFrames.FirstChild(), aWM, aCBSize, kidAvailableISize); @@ -434,8 +433,8 @@ nsTableOuterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, InnerTableFrame(), aWM, aCBSize, kidAvailableISize - capISize); - } else if (captionSide == NS_STYLE_CAPTION_SIDE_BSTART || - captionSide == NS_STYLE_CAPTION_SIDE_BEND) { + } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { nscoord margin; inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM, aCBSize, kidAvailableISize, &margin); @@ -446,8 +445,8 @@ nsTableOuterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, inlineSize = capISize; } } else { - NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE || - captionSide == NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE, + NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE, "unexpected caption-side"); inlineSize = ChildShrinkWrapISize(aRenderingContext, InnerTableFrame(), aWM, aCBSize, kidAvailableISize); @@ -463,11 +462,10 @@ nsTableOuterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, } uint8_t -nsTableOuterFrame::GetLogicalCaptionSide(WritingMode aWM) +nsTableOuterFrame::GetCaptionSide() { if (mCaptionFrames.NotEmpty()) { - return mCaptionFrames.FirstChild()->StyleTableBorder()-> - LogicalCaptionSide(aWM); + return mCaptionFrames.FirstChild()->StyleTableBorder()->mCaptionSide; } else { return NO_SIDE; // no caption @@ -498,17 +496,17 @@ nsTableOuterFrame::SetDesiredSize(uint8_t aCaptionSide, // compute the overall inline-size switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_ISTART: + case NS_STYLE_CAPTION_SIDE_LEFT: aISize = - std::max(aInnerMargin.IStart(aWM), + std::max(aInnerMargin.LineLeft(aWM), aCaptionMargin.IStartEnd(aWM) + aCaptionSize.ISize(aWM)) + - aInnerSize.ISize(aWM) + aInnerMargin.IEnd(aWM); + aInnerSize.ISize(aWM) + aInnerMargin.LineRight(aWM); break; - case NS_STYLE_CAPTION_SIDE_IEND: + case NS_STYLE_CAPTION_SIDE_RIGHT: aISize = - std::max(aInnerMargin.IEnd(aWM), + std::max(aInnerMargin.LineRight(aWM), aCaptionMargin.IStartEnd(aWM) + aCaptionSize.ISize(aWM)) + - aInnerSize.ISize(aWM) + aInnerMargin.IStart(aWM); + aInnerSize.ISize(aWM) + aInnerMargin.LineLeft(aWM); break; default: aISize = @@ -519,22 +517,22 @@ nsTableOuterFrame::SetDesiredSize(uint8_t aCaptionSide, // compute the overall block-size switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_BSTART: - case NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_TOP: + case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: aBSize = aInnerSize.BSize(aWM) + aInnerMargin.BEnd(aWM); aBSize += std::max(aInnerMargin.BStart(aWM), aCaptionSize.BSize(aWM) + aCaptionMargin.BStartEnd(aWM)); break; - case NS_STYLE_CAPTION_SIDE_BEND: - case NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_BOTTOM: + case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: aBSize = aInnerSize.BSize(aWM) + aInnerMargin.BStart(aWM); aBSize += std::max(aInnerMargin.BEnd(aWM), aCaptionSize.BSize(aWM) + aCaptionMargin.BStartEnd(aWM)); break; - case NS_STYLE_CAPTION_SIDE_ISTART: - case NS_STYLE_CAPTION_SIDE_IEND: + case NS_STYLE_CAPTION_SIDE_LEFT: + case NS_STYLE_CAPTION_SIDE_RIGHT: aBSize = aInnerMargin.BStart(aWM); aBSize += std::max(aInnerSize.BSize(aWM) + aInnerMargin.BEnd(aWM), @@ -579,28 +577,28 @@ nsTableOuterFrame::GetCaptionOrigin(uint32_t aCaptionSide, // inline-dir computation switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_BEND: - case NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_BOTTOM: + case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: aOrigin.I(aWM) = aCaptionMargin.IStart(aWM); - if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BEND) { + if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // We placed the caption using only the table's isize as available // isize, and we should position it this way as well. aOrigin.I(aWM) += aInnerMargin.IStart(aWM); } break; - case NS_STYLE_CAPTION_SIDE_ISTART: + case NS_STYLE_CAPTION_SIDE_LEFT: + case NS_STYLE_CAPTION_SIDE_RIGHT: aOrigin.I(aWM) = aCaptionMargin.IStart(aWM); - break; - case NS_STYLE_CAPTION_SIDE_IEND: - aOrigin.I(aWM) = aInnerMargin.IStart(aWM) + aInnerSize.ISize(aWM) + - aCaptionMargin.IStart(aWM); + if (aWM.IsBidiLTR() == (aCaptionSide == NS_STYLE_CAPTION_SIDE_RIGHT)) { + aOrigin.I(aWM) += aInnerMargin.IStart(aWM) + aInnerSize.ISize(aWM); + } break; default: // block-start - NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_BSTART || - aCaptionSide == NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE, + NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP || + aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE, "unexpected caption side"); aOrigin.I(aWM) = aCaptionMargin.IStart(aWM); - if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BSTART) { + if (aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP) { // We placed the caption using only the table's isize as available // isize, and we should position it this way as well. aOrigin.I(aWM) += aInnerMargin.IStart(aWM); @@ -609,8 +607,8 @@ nsTableOuterFrame::GetCaptionOrigin(uint32_t aCaptionSide, } // block-dir computation switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_IEND: - case NS_STYLE_CAPTION_SIDE_ISTART: + case NS_STYLE_CAPTION_SIDE_RIGHT: + case NS_STYLE_CAPTION_SIDE_LEFT: aOrigin.B(aWM) = aInnerMargin.BStart(aWM); switch (GetCaptionVerticalAlign()) { case NS_STYLE_VERTICAL_ALIGN_MIDDLE: @@ -627,13 +625,13 @@ nsTableOuterFrame::GetCaptionOrigin(uint32_t aCaptionSide, break; } break; - case NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE: - case NS_STYLE_CAPTION_SIDE_BEND: + case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_BOTTOM: aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aInnerSize.BSize(aWM) + aCaptionMargin.BStart(aWM); break; - case NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE: - case NS_STYLE_CAPTION_SIDE_BSTART: + case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_TOP: aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aCaptionMargin.BStart(aWM); break; default: @@ -675,21 +673,23 @@ nsTableOuterFrame::GetInnerOrigin(uint32_t aCaptionSide, // inline-dir computation switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_ISTART: - if (aInnerMargin.IStart(aWM) < minCapISize) { - // shift the inner table to get some place for the caption - aInnerMargin.IEnd(aWM) += aInnerMargin.IStart(aWM) - minCapISize; - aInnerMargin.IEnd(aWM) = std::max(0, aInnerMargin.IEnd(aWM)); - aInnerMargin.IStart(aWM) = minCapISize; + case NS_STYLE_CAPTION_SIDE_LEFT: + case NS_STYLE_CAPTION_SIDE_RIGHT: + if (aWM.IsBidiLTR() == (aCaptionSide == NS_STYLE_CAPTION_SIDE_LEFT)) { + if (aInnerMargin.IStart(aWM) < minCapISize) { + // shift the inner table to get some place for the caption + aInnerMargin.IEnd(aWM) += aInnerMargin.IStart(aWM) - minCapISize; + aInnerMargin.IEnd(aWM) = std::max(0, aInnerMargin.IEnd(aWM)); + aInnerMargin.IStart(aWM) = minCapISize; + } } aOrigin.I(aWM) = aInnerMargin.IStart(aWM); break; default: - NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_BSTART || - aCaptionSide == NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE || - aCaptionSide == NS_STYLE_CAPTION_SIDE_BEND || - aCaptionSide == NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE || - aCaptionSide == NS_STYLE_CAPTION_SIDE_IEND || + NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP || + aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || + aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM || + aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE || aCaptionSide == NO_SIDE, "unexpected caption side"); aOrigin.I(aWM) = aInnerMargin.IStart(aWM); @@ -698,12 +698,12 @@ nsTableOuterFrame::GetInnerOrigin(uint32_t aCaptionSide, // block-dir computation switch (aCaptionSide) { - case NS_STYLE_CAPTION_SIDE_BEND: - case NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_BOTTOM: + case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: aOrigin.B(aWM) = aInnerMargin.BStart(aWM); break; - case NS_STYLE_CAPTION_SIDE_ISTART: - case NS_STYLE_CAPTION_SIDE_IEND: + case NS_STYLE_CAPTION_SIDE_LEFT: + case NS_STYLE_CAPTION_SIDE_RIGHT: aOrigin.B(aWM) = aInnerMargin.BStart(aWM); switch (GetCaptionVerticalAlign()) { case NS_STYLE_VERTICAL_ALIGN_MIDDLE: @@ -721,8 +721,8 @@ nsTableOuterFrame::GetInnerOrigin(uint32_t aCaptionSide, } break; case NO_SIDE: - case NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE: - case NS_STYLE_CAPTION_SIDE_BSTART: + case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_TOP: aOrigin.B(aWM) = aInnerMargin.BStart(aWM) + aCaptionSize.BSize(aWM) + aCaptionMargin.BStartEnd(aWM); break; @@ -771,9 +771,9 @@ nsTableOuterFrame::OuterBeginReflowChild(nsPresContext* aPresContext, // see if we need to reset top-of-page due to a caption if (aChildRS->mFlags.mIsTopOfPage && mCaptionFrames.FirstChild() == aChildFrame) { - uint8_t captionSide = GetLogicalCaptionSide(wm); - if (captionSide == NS_STYLE_CAPTION_SIDE_BEND || - captionSide == NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE) { + uint8_t captionSide = GetCaptionSide(); + if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) { aChildRS->mFlags.mIsTopOfPage = false; } } @@ -860,15 +860,15 @@ nsTableOuterFrame::Reflow(nsPresContext* aPresContext, // ComputeAutoSize has to match this logic. WritingMode wm = aOuterRS.GetWritingMode(); - uint8_t captionSide = GetLogicalCaptionSide(wm); + uint8_t captionSide = GetCaptionSide(); WritingMode captionWM = wm; // will be changed below if necessary if (captionSide == NO_SIDE) { // We don't have a caption. OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRS, aOuterRS.ComputedSize(wm).ISize(wm)); - } else if (captionSide == NS_STYLE_CAPTION_SIDE_ISTART || - captionSide == NS_STYLE_CAPTION_SIDE_IEND) { + } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT || + captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) { // ComputeAutoSize takes care of making side captions small. Compute // the caption's size first, and tell the table to fit in what's left. OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS, @@ -878,8 +878,8 @@ nsTableOuterFrame::Reflow(nsPresContext* aPresContext, captionRS->ComputedSizeWithMarginBorderPadding(wm).ISize(wm); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRS, innerAvailISize); - } else if (captionSide == NS_STYLE_CAPTION_SIDE_BSTART || - captionSide == NS_STYLE_CAPTION_SIDE_BEND) { + } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // Compute the table's size first, and then prevent the caption from // being larger in the inline dir unless it has to be. // @@ -901,8 +901,8 @@ nsTableOuterFrame::Reflow(nsPresContext* aPresContext, captionRS, innerBorderISize); captionWM = captionRS->GetWritingMode(); } else { - NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE || - captionSide == NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE, + NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || + captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE, "unexpected caption-side"); // Size the table and the caption independently. captionWM = mCaptionFrames.FirstChild()->GetWritingMode(); @@ -932,10 +932,10 @@ nsTableOuterFrame::Reflow(nsPresContext* aPresContext, if (NS_UNCONSTRAINEDSIZE != aOuterRS.AvailableBSize()) { nscoord captionBSize = 0; switch (captionSide) { - case NS_STYLE_CAPTION_SIDE_BSTART: - case NS_STYLE_CAPTION_SIDE_BEND: - case NS_STYLE_CAPTION_SIDE_BSTART_OUTSIDE: - case NS_STYLE_CAPTION_SIDE_BEND_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_TOP: + case NS_STYLE_CAPTION_SIDE_BOTTOM: + case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: + case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: captionBSize = captionSize.BSize(wm) + captionMargin.BStartEnd(wm); break; } diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index 23956c747e..eb0453592c 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -188,14 +188,15 @@ protected: void InitChildReflowState(nsPresContext& aPresContext, nsHTMLReflowState& aReflowState); - // Get a NS_STYLE_CAPTION_SIDE_* value, with physically-specified sides - // resolved to logical sides, or NO_SIDE if no caption is present. - uint8_t GetLogicalCaptionSide(mozilla::WritingMode aWM); + // Get a NS_STYLE_CAPTION_SIDE_* value, or NO_SIDE if no caption is present. + // (Remember that caption-side values are interpreted logically, despite + // having "physical" names.) + uint8_t GetCaptionSide(); - bool HasSideCaption(mozilla::WritingMode aWM) { - uint8_t captionSide = GetLogicalCaptionSide(aWM); - return captionSide == NS_STYLE_CAPTION_SIDE_ISTART || - captionSide == NS_STYLE_CAPTION_SIDE_IEND; + bool HasSideCaption() { + uint8_t captionSide = GetCaptionSide(); + return captionSide == NS_STYLE_CAPTION_SIDE_LEFT || + captionSide == NS_STYLE_CAPTION_SIDE_RIGHT; } uint8_t GetCaptionVerticalAlign(); diff --git a/mfbt/XorShift128PlusRNG.h b/mfbt/XorShift128PlusRNG.h new file mode 100644 index 0000000000..fb4139fe0e --- /dev/null +++ b/mfbt/XorShift128PlusRNG.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* The xorshift128+ pseudo-random number generator. */ + +#ifndef mozilla_XorShift128Plus_h +#define mozilla_XorShift128Plus_h + +#include "mozilla/Assertions.h" +#include "mozilla/FloatingPoint.h" + +#include +#include +#include + +namespace mozilla { +namespace non_crypto { + +/* + * A stream of pseudo-random numbers generated using the xorshift+ technique + * described here: + * + * Vigna, Sebastiano (2014). "Further scramblings of Marsaglia's xorshift + * generators". arXiv:1404.0390 (http://arxiv.org/abs/1404.0390) + * + * That paper says: + * + * In particular, we propose a tightly coded xorshift128+ generator that + * does not fail systematically any test from the BigCrush suite of TestU01 + * (even reversed) and generates 64 pseudorandom bits in 1.10 ns on an + * Intel(R) Core(TM) i7-4770 CPU @3.40GHz (Haswell). It is the fastest + * generator we are aware of with such empirical statistical properties. + * + * This generator is not suitable as a cryptographically secure random number + * generator. + */ +class XorShift128PlusRNG { + uint64_t mState[2]; + + public: + /* + * Construct a xorshift128+ pseudo-random number stream using |aInitial0| and + * |aInitial1| as the initial state. These may not both be zero; ideally, they + * should have an almost even mix of zero and one bits. + */ + XorShift128PlusRNG(uint64_t aInitial0, uint64_t aInitial1) { + setState(aInitial0, aInitial1); + } + + /* Return a pseudo-random 64-bit number. */ + uint64_t next() { + uint64_t s1 = mState[0]; + const uint64_t s0 = mState[1]; + mState[0] = s0; + s1 ^= s1 << 23; + mState[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26); + return mState[1] + s0; + } + + /* + * Return a pseudo-random floating-point value in the range [0, 1). + * More precisely, choose an integer in the range [0, 2**53) and + * divide it by 2**53. + */ + double nextDouble() { + /* + * Because the IEEE 64-bit floating point format stores the leading '1' bit + * of the mantissa implicitly, it effectively represents a mantissa in the + * range [0, 2**53) in only 52 bits. FloatingPoint::kExponentShift + * is the width of the bitfield in the in-memory format, so we must add one + * to get the mantissa's range. + */ + static const int kMantissaBits = + mozilla::FloatingPoint::kExponentShift + 1; + uint64_t mantissa = next() & ((1ULL << kMantissaBits) - 1); + return ldexp(static_cast(mantissa), -kMantissaBits); + } + + /* + * Set the stream's current state to |aState0| and |aState1|. These must not + * both be zero; ideally, they should have an almost even mix of zero and one + * bits. + */ + void setState(uint64_t aState0, uint64_t aState1) { + MOZ_ASSERT(aState0 || aState1); + mState[0] = aState0; + mState[1] = aState1; + } +}; + +} // namespace non_crypto +} // namespace mozilla + +#endif // mozilla_XorShift128Plus_h diff --git a/mfbt/moz.build b/mfbt/moz.build index d4fe3e8198..d3ba9e1de6 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -95,6 +95,7 @@ EXPORTS.mozilla = [ 'Variant.h', 'Vector.h', 'WeakPtr.h', + 'XorShift128PlusRNG.h', 'unused.h', ] diff --git a/mfbt/tests/TestXorShift128PlusRNG.cpp b/mfbt/tests/TestXorShift128PlusRNG.cpp new file mode 100644 index 0000000000..dbe83d049e --- /dev/null +++ b/mfbt/tests/TestXorShift128PlusRNG.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include "mozilla/Assertions.h" +#include "mozilla/PodOperations.h" +#include "mozilla/XorShift128PlusRNG.h" + +using mozilla::non_crypto::XorShift128PlusRNG; + +static void +TestDumbSequence() +{ + XorShift128PlusRNG rng(1, 4); + + // Calculated by hand following the algorithm given in the paper. The upper + // bits are mostly zero because we started with a poor seed; once it has run + // for a while, we'll get an even mix of ones and zeros in all 64 bits. + MOZ_RELEASE_ASSERT(rng.next() == 0x800049); + MOZ_RELEASE_ASSERT(rng.next() == 0x3000186); + MOZ_RELEASE_ASSERT(rng.next() == 0x400003001145); + + // Using ldexp here lets us write out the mantissa in hex, so we can compare + // them with the results generated by hand. + MOZ_RELEASE_ASSERT(rng.nextDouble() + == ldexp(static_cast(0x1400003105049), -53)); + MOZ_RELEASE_ASSERT(rng.nextDouble() + == ldexp(static_cast(0x2000802e49146), -53)); + MOZ_RELEASE_ASSERT(rng.nextDouble() + == ldexp(static_cast(0x248300468544d), -53)); +} + +static size_t +Population(uint64_t n) +{ + size_t pop = 0; + + while (n > 0) { + n &= n-1; // Clear the rightmost 1-bit in n. + pop++; + } + + return pop; +} + +static void +TestPopulation() +{ + XorShift128PlusRNG rng(698079309544035222ULL, 6012389156611637584ULL); + + // Give it some time to warm up; it should tend towards more + // even distributions of zeros and ones. + for (size_t i = 0; i < 40; i++) + rng.next(); + + for (size_t i = 0; i < 40; i++) { + size_t pop = Population(rng.next()); + MOZ_RELEASE_ASSERT(24 <= pop && pop <= 40); + } +} + +static void +TestSetState() +{ + static const uint64_t seed[2] = { 1795644156779822404ULL, 14162896116325912595ULL }; + XorShift128PlusRNG rng(seed[0], seed[1]); + + const size_t n = 10; + uint64_t log[n]; + + for (size_t i = 0; i < n; i++) + log[i] = rng.next(); + + rng.setState(seed[0], seed[1]); + + for (size_t i = 0; i < n; i++) + MOZ_RELEASE_ASSERT(log[i] == rng.next()); +} + +static void +TestDoubleDistribution() +{ + XorShift128PlusRNG rng(0xa207aaede6859736, 0xaca6ca5060804791); + + const size_t n = 100; + size_t bins[n]; + mozilla::PodArrayZero(bins); + + // This entire file runs in 0.006s on my laptop. Generating + // more numbers lets us put tighter bounds on the bins. + for (size_t i = 0; i < 100000; i++) { + double d = rng.nextDouble(); + MOZ_RELEASE_ASSERT(0.0 <= d && d < 1.0); + bins[(int) (d * n)]++; + } + + for (size_t i = 0; i < n; i++) { + MOZ_RELEASE_ASSERT(900 <= bins[i] && bins[i] <= 1100); + } +} + +int +main() +{ + TestDumbSequence(); + TestPopulation(); + TestSetState(); + TestDoubleDistribution(); + + return 0; +} diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 0ddb14323e..a2b495acc3 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -42,6 +42,7 @@ CppUnitTests([ 'TestVariant', 'TestVector', 'TestWeakPtr', + 'TestXorShift128PlusRNG', ]) if not CONFIG['MOZ_ASAN']: diff --git a/toolkit/devtools/server/actors/csscoverage.js b/toolkit/devtools/server/actors/csscoverage.js index ea2e19b89f..02a42d1e58 100644 --- a/toolkit/devtools/server/actors/csscoverage.js +++ b/toolkit/devtools/server/actors/csscoverage.js @@ -564,8 +564,9 @@ function getImportedSheets(stylesheet) { * @see deconstructRuleId(ruleId) */ function ruleToId(rule) { - let loc = stylesheets.getRuleLocation(rule); - return sheetToUrl(rule.parentStyleSheet) + "|" + loc.line + "|" + loc.column; + let line = DOMUtils.getRelativeRuleLine(rule); + let column = DOMUtils.getRuleColumn(rule); + return sheetToUrl(rule.parentStyleSheet) + "|" + line + "|" + column; } /** diff --git a/toolkit/devtools/server/actors/stylesheets.js b/toolkit/devtools/server/actors/stylesheets.js index 95881ca3bb..82d4d5e103 100644 --- a/toolkit/devtools/server/actors/stylesheets.js +++ b/toolkit/devtools/server/actors/stylesheets.js @@ -912,53 +912,6 @@ let StyleSheetActor = protocol.ActorClass({ } }) -/** - * Find the line/column for a rule. - * This is like DOMUtils.getRule[Line|Column] except for inline + + +
Styled Node
+
Styled Node
+
Styled Node
+ + diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index e82944e989..f8ec8c7369 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -53,7 +53,6 @@ #include "js/TypeDecls.h" #endif #include "mozilla/UniquePtr.h" -#include "mozilla/GuardObjects.h" namespace mozilla { class TimeStamp; diff --git a/xpcom/glue/nsHashKeys.h b/xpcom/glue/nsHashKeys.h index 9ed477dab3..462728a10a 100644 --- a/xpcom/glue/nsHashKeys.h +++ b/xpcom/glue/nsHashKeys.h @@ -651,6 +651,17 @@ private: nsCOMPtr mKey; }; +namespace mozilla { + +template +PLDHashNumber +Hash(const T& aValue) +{ + return aValue.Hash(); +} + +} // namespace mozilla + /** * Hashtable key class to use with objects for which Hash() and operator==() * are defined. @@ -669,7 +680,7 @@ public: bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mKey; } static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } - static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->Hash(); } + static PLDHashNumber HashKey(KeyTypePointer aKey) { return ::mozilla::Hash(*aKey); } enum { ALLOW_MEMMOVE = true }; private: