Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/layout/style/./../../../layout/style/GeckoBindings.cpp
Warning:line 1102, column 3
Value stored to 'keyframeIndex' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_layout_style2.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/layout/style -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/layout/style -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/layout/style -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/layout/style -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/xul -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/html -I /root/firefox-clang/dom/xul -I /root/firefox-clang/image -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c++ Unified_cpp_layout_style2.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/* FFI functions for Servo to call into Gecko */
6
7#include "mozilla/GeckoBindings.h"
8
9#include "AnchorPositioningUtils.h"
10#include "ChildIterator.h"
11#include "ErrorReporter.h"
12#include "PseudoStyleType.h"
13#include "gfxFontFeatures.h"
14#include "gfxMathTable.h"
15#include "gfxTextRun.h"
16#include "imgLoader.h"
17#include "mozilla/AttributeStyles.h"
18#include "mozilla/ClearOnShutdown.h"
19#include "mozilla/DeclarationBlock.h"
20#include "mozilla/EffectCompositor.h"
21#include "mozilla/EffectSet.h"
22#include "mozilla/FontPropertyTypes.h"
23#include "mozilla/Hal.h"
24#include "mozilla/Keyframe.h"
25#include "mozilla/LookAndFeel.h"
26#include "mozilla/Mutex.h"
27#include "mozilla/Preferences.h"
28#include "mozilla/ReflowInput.h"
29#include "mozilla/RestyleManager.h"
30#include "mozilla/ServoBindings.h"
31#include "mozilla/ServoElementSnapshot.h"
32#include "mozilla/ServoTraversalStatistics.h"
33#include "mozilla/ShadowParts.h"
34#include "mozilla/SizeOfState.h"
35#include "mozilla/StaticPrefs_browser.h"
36#include "mozilla/StaticPrefs_layout.h"
37#include "mozilla/StaticPresData.h"
38#include "mozilla/StaticPtr.h"
39#include "mozilla/StyleAnimationValue.h"
40#include "mozilla/TimelineManager.h"
41#include "mozilla/URLExtraData.h"
42#include "mozilla/css/ImageLoader.h"
43#include "mozilla/dom/CSSMozDocumentRule.h"
44#include "mozilla/dom/CSSTransition.h"
45#include "mozilla/dom/DocumentInlines.h"
46#include "mozilla/dom/Element.h"
47#include "mozilla/dom/ElementInlines.h"
48#include "mozilla/dom/HTMLBodyElement.h"
49#include "mozilla/dom/HTMLImageElement.h"
50#include "mozilla/dom/HTMLSelectElement.h"
51#include "mozilla/dom/HTMLSlotElement.h"
52#include "mozilla/dom/HTMLTableCellElement.h"
53#include "mozilla/dom/MediaList.h"
54#include "mozilla/dom/ReferrerInfo.h"
55#include "mozilla/dom/SVGElement.h"
56#include "mozilla/dom/ViewTransition.h"
57#include "mozilla/dom/WorkerCommon.h"
58#include "nsAnimationManager.h"
59#include "nsAttrValueInlines.h"
60#include "nsCSSFrameConstructor.h"
61#include "nsCSSProps.h"
62#include "nsCharSeparatedTokenizer.h"
63#include "nsContentUtils.h"
64#include "nsDOMTokenList.h"
65#include "nsDeviceContext.h"
66#include "nsFontMetrics.h"
67#include "nsIContentInlines.h"
68#include "nsIFrame.h"
69#include "nsIFrameInlines.h"
70#include "nsILoadContext.h"
71#include "nsINode.h"
72#include "nsIURI.h"
73#include "nsLayoutUtils.h"
74#include "nsNameSpaceManager.h"
75#include "nsNetUtil.h"
76#include "nsProxyRelease.h"
77#include "nsString.h"
78#include "nsStyleStruct.h"
79#include "nsStyleUtil.h"
80#include "nsTArray.h"
81#include "nsTransitionManager.h"
82#include "nsWindowSizes.h"
83
84#if defined(MOZ_MEMORY1)
85# include "mozmemory.h"
86#endif
87
88using namespace mozilla;
89using namespace mozilla::css;
90using namespace mozilla::dom;
91
92ServoTraversalStatistics* ServoTraversalStatistics::sSingleton = nullptr;
93
94static StaticAutoPtr<Mutex> sServoFFILock;
95/*
96 * Does this child count as significant for selector matching?
97 *
98 * See nsStyleUtil::IsSignificantChild for details.
99 */
100bool Gecko_IsSignificantChild(const nsINode* aNode,
101 bool aWhitespaceIsSignificant) {
102 return nsStyleUtil::ThreadSafeIsSignificantChild(aNode->AsContent(),
103 aWhitespaceIsSignificant);
104}
105
106const nsINode* Gecko_GetLastChild(const nsINode* aNode) {
107 return aNode->GetLastChild();
108}
109
110const nsINode* Gecko_GetFlattenedTreeParentNode(const nsINode* aNode) {
111 return aNode->GetFlattenedTreeParentNodeForStyle();
112}
113
114void Gecko_GetAnonymousContentForElement(const Element* aElement,
115 nsTArray<nsIContent*>* aArray) {
116 MOZ_ASSERT(aElement->MayHaveAnonymousChildren())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement->MayHaveAnonymousChildren())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aElement->MayHaveAnonymousChildren()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement->MayHaveAnonymousChildren()"
, "./../../../layout/style/GeckoBindings.cpp", 116); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElement->MayHaveAnonymousChildren()" ")"
); do { MOZ_CrashSequence(__null, 116); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
117 nsLayoutUtils::AppendGeneratedContentPseudos(aElement, *aArray);
118 nsContentUtils::AppendNativeAnonymousChildren(
119 aElement, *aArray, nsIContent::eSkipDocumentLevelNativeAnonymousContent);
120}
121
122void Gecko_DestroyAnonymousContentList(nsTArray<nsIContent*>* aAnonContent) {
123 MOZ_ASSERT(aAnonContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aAnonContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aAnonContent))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aAnonContent", "./../../../layout/style/GeckoBindings.cpp"
, 123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAnonContent"
")"); do { MOZ_CrashSequence(__null, 123); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
124 delete aAnonContent;
125}
126
127RustSpan<const nsINode* const> Gecko_GetAssignedNodes(const Element* aElement) {
128 MOZ_ASSERT(HTMLSlotElement::FromNode(aElement))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(HTMLSlotElement::FromNode(aElement))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(HTMLSlotElement::FromNode(aElement
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("HTMLSlotElement::FromNode(aElement)", "./../../../layout/style/GeckoBindings.cpp"
, 128); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HTMLSlotElement::FromNode(aElement)"
")"); do { MOZ_CrashSequence(__null, 128); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
129 Span<const RefPtr<nsINode>> span =
130 static_cast<const HTMLSlotElement*>(aElement)->AssignedNodes();
131 return {reinterpret_cast<const nsINode* const*>(span.Elements()),
132 span.Length()};
133}
134
135void Gecko_GetQueryContainerSize(const Element* aElement, nscoord* aOutWidth,
136 nscoord* aOutHeight) {
137 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../layout/style/GeckoBindings.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 137); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
138 const nsIFrame* frame = aElement->GetPrimaryFrame();
139 if (!frame) {
140 return;
141 }
142 const auto containAxes = frame->GetContainSizeAxes();
143 if (!containAxes.IsAny()) {
144 return;
145 }
146 nsSize size = frame->GetContentRectRelativeToSelf().Size();
147 bool isVertical = frame->GetWritingMode().IsVertical();
148 if (isVertical ? containAxes.mBContained : containAxes.mIContained) {
149 *aOutWidth = size.width;
150 }
151 if (isVertical ? containAxes.mIContained : containAxes.mBContained) {
152 *aOutHeight = size.height;
153 }
154}
155
156void Gecko_ComputedStyle_Init(ComputedStyle* aStyle,
157 const ServoComputedData* aValues) {
158 new (KnownNotNull, aStyle) ComputedStyle(ServoComputedDataForgotten(aValues));
159}
160
161ServoComputedData::ServoComputedData(const ServoComputedDataForgotten aValue) {
162 memcpy((void*)this, aValue.mPtr, sizeof(*this));
163}
164
165MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoStyleStructsMallocEnclosingSizeOf)static size_t ServoStyleStructsMallocEnclosingSizeOf(const void
* aPtr) { jemalloc_ptr_info_t info; jemalloc_ptr_info(aPtr, &
info); mozilla::dmd::Report(info.addr); return jemalloc_ptr_is_live
(&info) ? info.size : 0; }
166
167void ServoComputedData::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const {
168 // Note: GetStyleFoo() returns a pointer to an nsStyleFoo that sits within a
169 // servo_arc::Arc, i.e. it is preceded by a word-sized refcount. So we need
170 // to measure it with a function that can handle an interior pointer. We use
171 // ServoStyleStructsEnclosingMallocSizeOf to clearly identify in DMD's
172 // output the memory measured here.
173#define MEASURE_STRUCT(name_) \
174 static_assert(alignof(nsStyle##name_) <= sizeof(size_t), \
175 "alignment will break AddSizeOfExcludingThis()"); \
176 const void* p##name_ = Style##name_(); \
177 if (!aSizes.mState.HaveSeenPtr(p##name_)) { \
178 aSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_)mStylename_ += \
179 ServoStyleStructsMallocEnclosingSizeOf(p##name_); \
180 }
181 FOR_EACH_STYLE_STRUCT(MEASURE_STRUCT, MEASURE_STRUCT)MEASURE_STRUCT(Font) MEASURE_STRUCT(List) MEASURE_STRUCT(Text
) MEASURE_STRUCT(Visibility) MEASURE_STRUCT(UI) MEASURE_STRUCT
(TableBorder) MEASURE_STRUCT(SVG) MEASURE_STRUCT(Background) MEASURE_STRUCT
(Position) MEASURE_STRUCT(TextReset) MEASURE_STRUCT(Display) MEASURE_STRUCT
(Content) MEASURE_STRUCT(UIReset) MEASURE_STRUCT(Table) MEASURE_STRUCT
(Margin) MEASURE_STRUCT(Padding) MEASURE_STRUCT(Border) MEASURE_STRUCT
(Outline) MEASURE_STRUCT(XUL) MEASURE_STRUCT(SVGReset) MEASURE_STRUCT
(Column) MEASURE_STRUCT(Effects) MEASURE_STRUCT(Page)
182#undef MEASURE_STRUCT
183
184 if (visited_style && !aSizes.mState.HaveSeenPtr(visited_style)) {
185 visited_style->AddSizeOfIncludingThis(aSizes,
186 &aSizes.mLayoutComputedValuesVisited);
187 }
188
189 // Measurement of the following members may be added later if DMD finds it is
190 // worthwhile:
191 // - custom_properties
192 // - writing_mode
193 // - rules
194 // - font_computation_data
195}
196
197void Gecko_ComputedStyle_Destroy(ComputedStyle* aStyle) {
198 aStyle->~ComputedStyle();
199}
200
201void Gecko_ConstructStyleChildrenIterator(const Element* aElement,
202 StyleChildrenIterator* aIterator) {
203 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../layout/style/GeckoBindings.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
204 MOZ_ASSERT(aIterator)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIterator)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aIterator))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aIterator", "./../../../layout/style/GeckoBindings.cpp"
, 204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIterator" ")"
); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
205 new (aIterator) StyleChildrenIterator(aElement);
206}
207
208void Gecko_DestroyStyleChildrenIterator(StyleChildrenIterator* aIterator) {
209 MOZ_ASSERT(aIterator)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIterator)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aIterator))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aIterator", "./../../../layout/style/GeckoBindings.cpp"
, 209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIterator" ")"
); do { MOZ_CrashSequence(__null, 209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
210
211 aIterator->~StyleChildrenIterator();
212}
213
214const nsINode* Gecko_GetNextStyleChild(StyleChildrenIterator* aIterator) {
215 MOZ_ASSERT(aIterator)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIterator)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aIterator))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aIterator", "./../../../layout/style/GeckoBindings.cpp"
, 215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIterator" ")"
); do { MOZ_CrashSequence(__null, 215); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
216 return aIterator->GetNextChild();
217}
218
219bool Gecko_VisitedStylesEnabled(const Document* aDoc) {
220 MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc", "./../../../layout/style/GeckoBindings.cpp"
, 220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")"); do
{ MOZ_CrashSequence(__null, 220); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
221 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 221); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 221); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
222
223 if (!StaticPrefs::layout_css_visited_links_enabled()) {
224 return false;
225 }
226
227 if (aDoc->IsBeingUsedAsImage()) {
228 return false;
229 }
230
231 nsILoadContext* loadContext = aDoc->GetLoadContext();
232 if (loadContext && loadContext->UsePrivateBrowsing()) {
233 return false;
234 }
235
236 return true;
237}
238
239ElementState::InternalType Gecko_ElementState(const Element* aElement) {
240 return aElement->StyleState().GetInternalValue();
241}
242
243bool Gecko_IsRootElement(const Element* aElement) {
244 return aElement->OwnerDoc()->GetRootElement() == aElement;
245}
246
247void Gecko_GetCachedLazyPseudoStyles(const ComputedStyle* aStyle,
248 nsTArray<const ComputedStyle*>* aArray) {
249 MOZ_ASSERT(aStyle)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyle)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aStyle))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aStyle", "./../../../layout/style/GeckoBindings.cpp"
, 249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyle" ")")
; do { MOZ_CrashSequence(__null, 249); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
250 aStyle->GetCachedLazyPseudoStyles(*aArray);
251}
252
253void Gecko_NoteDirtyElement(const Element* aElement) {
254 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 254); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 254); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
255 const_cast<Element*>(aElement)->NoteDirtyForServo();
256}
257
258void Gecko_NoteDirtySubtreeForInvalidation(const Element* aElement) {
259 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 259); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 259); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
260 const_cast<Element*>(aElement)->NoteDirtySubtreeForServo();
261}
262
263void Gecko_NoteAnimationOnlyDirtyElement(const Element* aElement) {
264 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 264); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 264); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
265 const_cast<Element*>(aElement)->NoteAnimationOnlyDirtyForServo();
266}
267
268bool Gecko_AnimationNameMayBeReferencedFromStyle(
269 const nsPresContext* aPresContext, nsAtom* aName) {
270 MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext", "./../../../layout/style/GeckoBindings.cpp"
, 270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 270); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
271 return aPresContext->AnimationManager()->AnimationMayBeReferenced(aName);
272}
273
274void Gecko_InvalidatePositionTry(const Element* aElement) {
275 auto* f = aElement->GetPrimaryFrame();
276 if (!f || !f->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
277 return;
278 }
279 f->RemoveProperty(nsIFrame::LastSuccessfulPositionFallback());
280 f->PresShell()->MarkPositionedFrameForReflow(f);
281}
282
283void Gecko_NoteHighlightPseudoStyleInvalidated(const Document* aDoc) {
284 if (auto* presContext = aDoc->GetPresContext()) {
285 presContext->RestyleManager()->NoteHighlightPseudoStyleInvalidated();
286 }
287}
288
289float Gecko_GetScrollbarInlineSize(const nsPresContext* aPc) {
290 MOZ_ASSERT(aPc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aPc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aPc", "./../../../layout/style/GeckoBindings.cpp"
, 290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPc" ")"); do
{ MOZ_CrashSequence(__null, 290); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
291 auto overlay = aPc->UseOverlayScrollbars() ? nsITheme::Overlay::Yes
292 : nsITheme::Overlay::No;
293 LayoutDeviceIntCoord size =
294 aPc->Theme()->GetScrollbarSize(aPc, StyleScrollbarWidth::Auto, overlay);
295 return aPc->DevPixelsToFloatCSSPixels(size);
296}
297
298PseudoStyleType Gecko_GetImplementedPseudoType(const Element* aElement) {
299 return aElement->GetPseudoElementType();
300}
301
302nsAtom* Gecko_GetImplementedPseudoIdentifier(const Element* aElement) {
303 if (!aElement->HasName()) {
304 return nullptr;
305 }
306
307 PseudoStyleType type = aElement->GetPseudoElementType();
308 if (!PseudoStyle::IsNamedViewTransitionPseudoElement(type) &&
309 type != PseudoStyleType::Picker) {
310 return nullptr;
311 }
312
313 return aElement->GetParsedAttr(nsGkAtoms::name)->GetAtomValue();
314}
315
316uint32_t Gecko_CalcStyleDifference(const ComputedStyle* aOldStyle,
317 const ComputedStyle* aNewStyle,
318 bool* aAnyStyleStructChanged,
319 bool* aOnlyResetStructsChanged) {
320 MOZ_ASSERT(aOldStyle)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOldStyle)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOldStyle))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aOldStyle", "./../../../layout/style/GeckoBindings.cpp"
, 320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOldStyle" ")"
); do { MOZ_CrashSequence(__null, 320); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
321 MOZ_ASSERT(aNewStyle)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewStyle)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewStyle))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewStyle", "./../../../layout/style/GeckoBindings.cpp"
, 321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewStyle" ")"
); do { MOZ_CrashSequence(__null, 321); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
322
323 uint32_t equalStructs;
324 nsChangeHint result =
325 aOldStyle->CalcStyleDifference(*aNewStyle, &equalStructs);
326
327 *aAnyStyleStructChanged =
328 equalStructs != StyleStructConstants::kAllStructsMask;
329
330 const auto kInheritedStructsMask =
331 StyleStructConstants::kInheritedStructsMask;
332 *aOnlyResetStructsChanged =
333 (equalStructs & kInheritedStructsMask) == kInheritedStructsMask;
334
335 return result;
336}
337
338nscoord Gecko_CalcLineHeight(const StyleLineHeight* aLh,
339 const nsPresContext* aPc, bool aVertical,
340 const nsStyleFont* aAgainstFont,
341 const mozilla::dom::Element* aElement) {
342 // Normal line-height depends on font metrics.
343 MutexAutoLock guard(*sServoFFILock);
344 return ReflowInput::CalcLineHeight(*aLh, *aAgainstFont,
345 const_cast<nsPresContext*>(aPc), aVertical,
346 aElement, 1.0f);
347}
348
349float Gecko_CalcAutoDecorationInset(float aFontSize) {
350 // Use an inset factor of 1/12.5, so we get 2px of inset (resulting in 4px
351 // gap between adjacent lines) at font-size 25px.
352 constexpr float kAutoInsetFactor = 1.0 / 12.5;
353
354 // Use the em size multiplied by kAutoInsetFactor, with a minimum of one
355 // CSS pixel to ensure that at least some separation occurs.
356 return std::max(1.0f, aFontSize * kAutoInsetFactor);
357}
358
359const ServoElementSnapshot* Gecko_GetElementSnapshot(
360 const ServoElementSnapshotTable* aTable, const Element* aElement) {
361 MOZ_ASSERT(aTable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTable)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aTable))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTable", "./../../../layout/style/GeckoBindings.cpp"
, 361); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTable" ")")
; do { MOZ_CrashSequence(__null, 361); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
362 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../layout/style/GeckoBindings.cpp"
, 362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
363
364 return aTable->Get(const_cast<Element*>(aElement));
365}
366
367bool Gecko_HaveSeenPtr(SeenPtrs* aTable, const void* aPtr) {
368 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 368); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 368); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
369 MOZ_ASSERT(aTable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTable)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aTable))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTable", "./../../../layout/style/GeckoBindings.cpp"
, 369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTable" ")")
; do { MOZ_CrashSequence(__null, 369); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
370 // Empty Rust allocations are indicated by small values up to the alignment
371 // of the relevant type. We shouldn't see anything like that here.
372 MOZ_ASSERT(uintptr_t(aPtr) > 16)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(uintptr_t(aPtr) > 16)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(uintptr_t(aPtr) > 16))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("uintptr_t(aPtr) > 16"
, "./../../../layout/style/GeckoBindings.cpp", 372); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "uintptr_t(aPtr) > 16" ")"); do { MOZ_CrashSequence
(__null, 372); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
373
374 return aTable->HaveSeenPtr(aPtr);
375}
376
377const StyleLockedDeclarationBlock* Gecko_GetStyleAttrDeclarationBlock(
378 const Element* aElement) {
379 return aElement->GetInlineStyleDeclaration();
380}
381
382const StyleLockedDeclarationBlock* Gecko_GetMappedAttributeDeclarations(
383 const Element* aElement) {
384 return aElement->GetMappedAttributeStyle();
385}
386
387const StyleLockedDeclarationBlock* Gecko_GetViewTransitionDynamicRule(
388 const Element* aElement) {
389 const auto* vt = aElement->OwnerDoc()->GetActiveViewTransition();
390 if (!vt) {
391 return nullptr;
392 }
393 return vt->GetDynamicRuleFor(*aElement);
394}
395
396const StyleLockedDeclarationBlock* Gecko_GetExtraContentStyleDeclarations(
397 const Element* aElement) {
398 if (const auto* cell = HTMLTableCellElement::FromNode(aElement)) {
399 return cell->GetMappedAttributesInheritedFromTable();
400 }
401 if (const auto* img = HTMLImageElement::FromNode(aElement)) {
402 return img->GetMappedAttributesFromSource();
403 }
404 return nullptr;
405}
406
407const StyleLockedDeclarationBlock* Gecko_GetUnvisitedLinkAttrDeclarationBlock(
408 const Element* aElement) {
409 AttributeStyles* attrStyles = aElement->OwnerDoc()->GetAttributeStyles();
410 if (!attrStyles) {
411 return nullptr;
412 }
413
414 return attrStyles->GetServoUnvisitedLinkDecl();
415}
416
417StyleSheet* Gecko_StyleSheet_Clone(const StyleSheet* aSheet) {
418 MOZ_ASSERT(aSheet)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSheet)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aSheet))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSheet", "./../../../layout/style/GeckoBindings.cpp"
, 418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSheet" ")")
; do { MOZ_CrashSequence(__null, 418); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
419 MOZ_ASSERT(aSheet->GetParentSheet(), "Should only be used for @import")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSheet->GetParentSheet())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSheet->GetParentSheet())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSheet->GetParentSheet()"
" (" "Should only be used for @import" ")", "./../../../layout/style/GeckoBindings.cpp"
, 419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSheet->GetParentSheet()"
") (" "Should only be used for @import" ")"); do { MOZ_CrashSequence
(__null, 419); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
420 // NOTE(emilio): We don't pass either the parent pointer of the stylesheet,
421 // nor fix up the child list (yet). This is fixed up in the StylesheetInner
422 // constructor.
423 RefPtr<StyleSheet> newSheet = aSheet->Clone(nullptr, nullptr);
424 return static_cast<StyleSheet*>(newSheet.forget().take());
425}
426
427void Gecko_StyleSheet_AddRef(const StyleSheet* aSheet) {
428 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 428); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 428); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
429 const_cast<StyleSheet*>(aSheet)->AddRef();
430}
431
432void Gecko_StyleSheet_Release(const StyleSheet* aSheet) {
433 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 433); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 433); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
434 const_cast<StyleSheet*>(aSheet)->Release();
435}
436
437GeckoImplicitScopeRoot Gecko_StyleSheet_ImplicitScopeRoot(
438 const mozilla::StyleSheet* aSheet) {
439 if (aSheet->IsConstructed()) {
440 return GeckoImplicitScopeRoot{
441 .mHost = nullptr, .mRoot = nullptr, .mConstructed = true};
442 }
443 // https://drafts.csswg.org/css-cascade-6/#scope-limits
444 // "If no <scope-start> is specified, the scoping root is the parent element
445 // of the owner node of the stylesheet where the @scope rule is defined."
446 const auto* node = aSheet->GetOwnerNodeOfOutermostSheet();
447 if (!node) {
448 return GeckoImplicitScopeRoot{
449 .mHost = nullptr, .mRoot = nullptr, .mConstructed = false};
450 }
451 const auto* host = node->GetContainingShadowHost();
452
453 if (auto* aElement = node->GetParentElement()) {
454 return GeckoImplicitScopeRoot{
455 .mHost = host, .mRoot = aElement, .mConstructed = false};
456 }
457 // "[...] If no such element exists, then the scoping root is the root of the
458 // containing node tree." This really should only happen for stylesheets
459 // defined at the edge of the shadow root.
460 return GeckoImplicitScopeRoot{
461 .mHost = host, .mRoot = host, .mConstructed = false};
462}
463
464const StyleLockedDeclarationBlock* Gecko_GetVisitedLinkAttrDeclarationBlock(
465 const Element* aElement) {
466 AttributeStyles* attrStyles = aElement->OwnerDoc()->GetAttributeStyles();
467 if (!attrStyles) {
468 return nullptr;
469 }
470 return attrStyles->GetServoVisitedLinkDecl();
471}
472
473const StyleLockedDeclarationBlock* Gecko_GetActiveLinkAttrDeclarationBlock(
474 const Element* aElement) {
475 AttributeStyles* attrStyles = aElement->OwnerDoc()->GetAttributeStyles();
476 if (!attrStyles) {
477 return nullptr;
478 }
479 return attrStyles->GetServoActiveLinkDecl();
480}
481
482bool Gecko_GetAnimationRule(const Element* aElement,
483 EffectCompositor::CascadeLevel aCascadeLevel,
484 StyleAnimationValueMap* aAnimationValues) {
485 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../layout/style/GeckoBindings.cpp"
, 485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
486
487 Document* doc = aElement->GetComposedDoc();
488 if (!doc) {
489 return false;
490 }
491 nsPresContext* presContext = doc->GetPresContext();
492 if (!presContext) {
493 return false;
494 }
495
496 const auto [element, pseudoRequest] =
497 AnimationUtils::GetElementPseudoPair(aElement);
498 return presContext->EffectCompositor()->GetServoAnimationRule(
499 element, pseudoRequest, aCascadeLevel, aAnimationValues);
500}
501
502bool Gecko_StyleAnimationsEquals(const nsStyleAutoArray<StyleAnimation>* aA,
503 const nsStyleAutoArray<StyleAnimation>* aB) {
504 return *aA == *aB;
505}
506
507bool Gecko_StyleScrollTimelinesEquals(
508 const nsStyleAutoArray<StyleScrollTimeline>* aA,
509 const nsStyleAutoArray<StyleScrollTimeline>* aB) {
510 return *aA == *aB;
511}
512
513bool Gecko_StyleViewTimelinesEquals(
514 const nsStyleAutoArray<StyleViewTimeline>* aA,
515 const nsStyleAutoArray<StyleViewTimeline>* aB) {
516 return *aA == *aB;
517}
518
519void Gecko_UpdateAnimations(const Element* aElement,
520 const ComputedStyle* aOldComputedData,
521 const ComputedStyle* aComputedData,
522 UpdateAnimationsTasks aTasks) {
523 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 523); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 523); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
524 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../layout/style/GeckoBindings.cpp"
, 524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
525
526 if (!aElement->IsInComposedDoc()) {
527 return;
528 }
529
530 nsPresContext* presContext = nsContentUtils::GetContextForContent(aElement);
531 if (!presContext || !presContext->IsDynamic()) {
532 return;
533 }
534
535 nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
536
537 const auto [element, pseudoRequest] =
538 AnimationUtils::GetElementPseudoPair(aElement);
539
540 // Handle timeline scopes first, because our own scroll/view-linked animations
541 // may be affected.
542 if (aTasks & UpdateAnimationsTasks::TimelineScopes) {
543 presContext->TimelineManager()->UpdateTimelineScopes(element,
544 aComputedData);
545 // We could try to limit the impact here, at least for changes involving not
546 // `all`. However, defer any such optimization until after bug 2024012.
547 presContext->AnimationManager()->UpdateAllNamedTimelineAnimations();
548 }
549
550 // Handle scroll/view timelines first because CSS animations may refer to the
551 // timeline defined by itself.
552 if (aTasks & UpdateAnimationsTasks::ScrollTimelines) {
553 const auto affected = presContext->TimelineManager()->UpdateTimelines(
554 const_cast<Element*>(element), pseudoRequest, aComputedData,
555 TimelineManager::ProgressTimelineType::Scroll);
556 presContext->AnimationManager()->UpdateNamedTimelineAnimations(affected);
557 }
558
559 if (aTasks & UpdateAnimationsTasks::ViewTimelines) {
560 const auto affected = presContext->TimelineManager()->UpdateTimelines(
561 const_cast<Element*>(element), pseudoRequest, aComputedData,
562 TimelineManager::ProgressTimelineType::View);
563 presContext->AnimationManager()->UpdateNamedTimelineAnimations(affected);
564 }
565
566 if (aTasks & UpdateAnimationsTasks::CSSAnimations) {
567 presContext->AnimationManager()->UpdateAnimations(
568 const_cast<Element*>(element), pseudoRequest, aComputedData);
569 }
570
571 // aComputedData might be nullptr if the target element is now in a
572 // display:none subtree. We still call Gecko_UpdateAnimations in this case
573 // because we need to stop CSS animations in the display:none subtree.
574 // However, we don't need to update transitions since they are stopped by
575 // RestyleManager::AnimationsWithDestroyedFrame so we just return early
576 // here.
577 if (!aComputedData) {
578 return;
579 }
580
581 if (aTasks & UpdateAnimationsTasks::CSSTransitions) {
582 MOZ_ASSERT(aOldComputedData)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOldComputedData)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOldComputedData))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aOldComputedData"
, "./../../../layout/style/GeckoBindings.cpp", 582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOldComputedData" ")"); do { MOZ_CrashSequence
(__null, 582); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
583 presContext->TransitionManager()->UpdateTransitions(
584 const_cast<Element*>(element), pseudoRequest, *aOldComputedData,
585 *aComputedData);
586 }
587
588 if (aTasks & UpdateAnimationsTasks::EffectProperties) {
589 presContext->EffectCompositor()->UpdateEffectProperties(
590 aComputedData, const_cast<Element*>(element), pseudoRequest);
591 }
592
593 if (aTasks & UpdateAnimationsTasks::CascadeResults) {
594 EffectSet* effectSet = EffectSet::Get(element, pseudoRequest);
595 // CSS animations/transitions might have been destroyed as part of the above
596 // steps so before updating cascade results, we check if there are still any
597 // animations to update.
598 if (effectSet) {
599 // We call UpdateCascadeResults directly (intead of
600 // MaybeUpdateCascadeResults) since we know for sure that the cascade has
601 // changed, but we were unable to call MarkCascadeUpdated when we noticed
602 // it since we avoid mutating state as part of the Servo parallel
603 // traversal.
604 presContext->EffectCompositor()->UpdateCascadeResults(
605 *effectSet, const_cast<Element*>(element), pseudoRequest);
606 }
607 }
608
609 if (aTasks & UpdateAnimationsTasks::DisplayChangedFromNone) {
610 presContext->EffectCompositor()->RequestRestyle(
611 const_cast<Element*>(element), pseudoRequest,
612 EffectCompositor::RestyleType::Standard,
613 EffectCompositor::CascadeLevel::Animations);
614 }
615}
616
617size_t Gecko_GetAnimationEffectCount(const Element* aElementOrPseudo) {
618 const auto [element, pseudo] =
619 AnimationUtils::GetElementPseudoPair(aElementOrPseudo);
620
621 EffectSet* effectSet = EffectSet::Get(element, pseudo);
622 return effectSet ? effectSet->Count() : 0;
623}
624
625bool Gecko_ElementHasAnimations(const Element* aElement) {
626 const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
627 return !!EffectSet::Get(element, pseudo);
628}
629
630bool Gecko_ElementHasCSSAnimations(const Element* aElement) {
631 const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
632 auto* collection =
633 nsAnimationManager::CSSAnimationCollection::Get(element, pseudo);
634 return collection && !collection->mAnimations.IsEmpty();
635}
636
637bool Gecko_ElementHasCSSTransitions(const Element* aElement) {
638 const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
639 auto* collection =
640 nsTransitionManager::CSSTransitionCollection::Get(element, pseudo);
641 return collection && !collection->mAnimations.IsEmpty();
642}
643
644size_t Gecko_ElementTransitions_Length(const Element* aElement) {
645 const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
646 auto* collection =
647 nsTransitionManager::CSSTransitionCollection::Get(element, pseudo);
648 return collection ? collection->mAnimations.Length() : 0;
649}
650
651static CSSTransition* GetCurrentTransitionAt(const Element* aElement,
652 size_t aIndex) {
653 const auto [element, pseudo] = AnimationUtils::GetElementPseudoPair(aElement);
654 auto* collection =
655 nsTransitionManager::CSSTransitionCollection ::Get(element, pseudo);
656 if (!collection) {
657 return nullptr;
658 }
659 return collection->mAnimations.SafeElementAt(aIndex);
660}
661
662NonCustomCSSPropertyId Gecko_ElementTransitions_PropertyAt(
663 const Element* aElement, size_t aIndex) {
664 CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
665 return transition ? transition->TransitionProperty().mId
666 : NonCustomCSSPropertyId::eCSSProperty_UNKNOWN;
667}
668
669const StyleAnimationValue* Gecko_ElementTransitions_EndValueAt(
670 const Element* aElement, size_t aIndex) {
671 CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
672 return transition ? transition->ToValue().mServo.get() : nullptr;
673}
674
675double Gecko_GetProgressFromComputedTiming(const ComputedTiming* aTiming) {
676 return aTiming->mProgress.Value();
677}
678
679double Gecko_GetPositionInSegment(const AnimationPropertySegment* aSegment,
680 double aProgress, bool aBeforeFlag) {
681 MOZ_ASSERT(aSegment->mFromKey < aSegment->mToKey,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSegment->mFromKey < aSegment->mToKey)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSegment->mFromKey < aSegment->mToKey))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSegment->mFromKey < aSegment->mToKey"
" (" "The segment from key should be less than to key" ")", "./../../../layout/style/GeckoBindings.cpp"
, 682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSegment->mFromKey < aSegment->mToKey"
") (" "The segment from key should be less than to key" ")")
; do { MOZ_CrashSequence(__null, 682); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
682 "The segment from key should be less than to key")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSegment->mFromKey < aSegment->mToKey)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aSegment->mFromKey < aSegment->mToKey))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aSegment->mFromKey < aSegment->mToKey"
" (" "The segment from key should be less than to key" ")", "./../../../layout/style/GeckoBindings.cpp"
, 682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSegment->mFromKey < aSegment->mToKey"
") (" "The segment from key should be less than to key" ")")
; do { MOZ_CrashSequence(__null, 682); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
683
684 double positionInSegment = (aProgress - aSegment->mFromKey) /
685 // To avoid floating precision inaccuracies, make
686 // sure we calculate both the numerator and
687 // denominator using double precision.
688 (double(aSegment->mToKey) - aSegment->mFromKey);
689
690 return StyleComputedTimingFunction::GetPortion(
691 aSegment->mTimingFunction, positionInSegment, aBeforeFlag);
692}
693
694const StyleAnimationValue* Gecko_AnimationGetBaseStyle(
695 const RawServoAnimationValueTable* aBaseStyles,
696 const mozilla::CSSPropertyId* aProperty) {
697 const auto* base = reinterpret_cast<const nsRefPtrHashtable<
698 nsGenericHashKey<CSSPropertyId>, StyleAnimationValue>*>(aBaseStyles);
699 return base->GetWeak(*aProperty);
700}
701
702void Gecko_FillAllImageLayers(nsStyleImageLayers* aLayers, uint32_t aMaxLen) {
703 aLayers->FillAllLayers(aMaxLen);
704}
705
706bool Gecko_IsDocumentBody(const Element* aElement) {
707 Document* doc = aElement->GetUncomposedDoc();
708 return doc && doc->GetBodyElement() == aElement;
709}
710
711bool Gecko_IsDarkColorScheme(const Document* aDoc,
712 const StyleColorSchemeFlags* aStyle) {
713 return LookAndFeel::ColorSchemeForStyle(*aDoc, *aStyle) == ColorScheme::Dark;
714}
715
716nscolor Gecko_ComputeSystemColor(StyleSystemColor aColor, const Document* aDoc,
717 const StyleColorSchemeFlags* aStyle) {
718 auto colorScheme = LookAndFeel::ColorSchemeForStyle(*aDoc, *aStyle);
719 const auto& prefs = PreferenceSheet::PrefsFor(*aDoc);
720 if (prefs.mMustUseLightSystemColors) {
721 colorScheme = ColorScheme::Light;
722 }
723 const auto& colors = prefs.ColorsFor(colorScheme);
724 switch (aColor) {
725 case StyleSystemColor::Canvastext:
726 return colors.mDefault;
727 case StyleSystemColor::Canvas:
728 return colors.mDefaultBackground;
729 case StyleSystemColor::Linktext:
730 return colors.mLink;
731 case StyleSystemColor::Activetext:
732 return colors.mActiveLink;
733 case StyleSystemColor::Visitedtext:
734 return colors.mVisitedLink;
735 default:
736 break;
737 }
738
739 auto useStandins = LookAndFeel::ShouldUseStandins(*aDoc, aColor);
740 return LookAndFeel::Color(aColor, colorScheme, useStandins);
741}
742
743int32_t Gecko_GetLookAndFeelInt(int32_t aId) {
744 auto intId = static_cast<LookAndFeel::IntID>(aId);
745 return LookAndFeel::GetInt(intId);
746}
747
748float Gecko_GetLookAndFeelFloat(int32_t aId) {
749 auto id = static_cast<LookAndFeel::FloatID>(aId);
750 return LookAndFeel::GetFloat(id);
751}
752
753bool Gecko_MatchLang(const Element* aElement, nsAtom* aOverrideLang,
754 bool aHasOverrideLang, const char16_t* aValue) {
755 MOZ_ASSERT(!(aOverrideLang && !aHasOverrideLang),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aOverrideLang && !aHasOverrideLang))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(aOverrideLang && !aHasOverrideLang)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!(aOverrideLang && !aHasOverrideLang)"
" (" "aHasOverrideLang should only be set when aOverrideLang is null"
")", "./../../../layout/style/GeckoBindings.cpp", 756); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(aOverrideLang && !aHasOverrideLang)"
") (" "aHasOverrideLang should only be set when aOverrideLang is null"
")"); do { MOZ_CrashSequence(__null, 756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
756 "aHasOverrideLang should only be set when aOverrideLang is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aOverrideLang && !aHasOverrideLang))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(aOverrideLang && !aHasOverrideLang)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!(aOverrideLang && !aHasOverrideLang)"
" (" "aHasOverrideLang should only be set when aOverrideLang is null"
")", "./../../../layout/style/GeckoBindings.cpp", 756); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(aOverrideLang && !aHasOverrideLang)"
") (" "aHasOverrideLang should only be set when aOverrideLang is null"
")"); do { MOZ_CrashSequence(__null, 756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
757 MOZ_ASSERT(aValue, "null lang parameter")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aValue)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aValue))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aValue" " (" "null lang parameter"
")", "./../../../layout/style/GeckoBindings.cpp", 757); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aValue" ") (" "null lang parameter" ")"); do
{ MOZ_CrashSequence(__null, 757); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
758 if (!aValue || !*aValue) {
759 return false;
760 }
761
762 // We have to determine the language of the current element. Since
763 // this is currently no property and since the language is inherited
764 // from the parent we have to be prepared to look at all parent
765 // nodes. The language itself is encoded in the LANG attribute.
766 if (auto* language = aHasOverrideLang ? aOverrideLang : aElement->GetLang()) {
767 return nsStyleUtil::LangTagCompare(nsAtomCString(language),
768 NS_ConvertUTF16toUTF8(aValue));
769 }
770
771 // Try to get the language from the HTTP header or if this
772 // is missing as well from the preferences.
773 // The content language can be a comma-separated list of
774 // language codes.
775 // FIXME: We're not really consistent in our treatment of comma-separated
776 // content-language values.
777 if (nsAtom* language = aElement->OwnerDoc()->GetContentLanguage()) {
778 const NS_ConvertUTF16toUTF8 langString(aValue);
779 nsAtomCString docLang(language);
780 docLang.StripWhitespace();
781 for (auto const& lang : docLang.Split(',')) {
782 if (nsStyleUtil::LangTagCompare(lang, langString)) {
783 return true;
784 }
785 }
786 }
787 return false;
788}
789
790bool Gecko_MatchViewTransitionClass(
791 const mozilla::dom::Element* aElement,
792 const nsTArray<StyleAtom>* aPtNameAndClassSelector) {
793 MOZ_ASSERT(aElement && aPtNameAndClassSelector)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement && aPtNameAndClassSelector)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aElement && aPtNameAndClassSelector))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aElement && aPtNameAndClassSelector"
, "./../../../layout/style/GeckoBindings.cpp", 793); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElement && aPtNameAndClassSelector"
")"); do { MOZ_CrashSequence(__null, 793); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
794
795 const Document* doc = aElement->OwnerDoc();
796 MOZ_ASSERT(doc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc", "./../../../layout/style/GeckoBindings.cpp"
, 796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ")"); do
{ MOZ_CrashSequence(__null, 796); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
797 const ViewTransition* vt = doc->GetActiveViewTransition();
798 if (!vt) {
799 // We can get here while lazily resolving the style of a named view
800 // transition pseudo-element that doesn't exist.
801 return false;
802 }
803 nsAtom* name = Gecko_GetImplementedPseudoIdentifier(aElement);
804 if (!name) {
805 return false;
806 }
807 return vt->MatchClassList(name, *aPtNameAndClassSelector);
808}
809
810static bool IsValidViewTransitionType(nsAtom* aName) {
811 nsDependentAtomString str(aName);
812 return !StringBeginsWith(str, u"-ua-"_ns,
813 nsASCIICaseInsensitiveStringComparator) &&
814 !str.LowerCaseEqualsASCII("none");
815}
816
817bool Gecko_HasActiveViewTransitionTypes(
818 const mozilla::dom::Document* aDoc,
819 const nsTArray<StyleCustomIdent>* aNames) {
820 MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc", "./../../../layout/style/GeckoBindings.cpp"
, 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")"); do
{ MOZ_CrashSequence(__null, 820); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
821 MOZ_ASSERT(aNames)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNames)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNames))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNames", "./../../../layout/style/GeckoBindings.cpp"
, 821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNames" ")")
; do { MOZ_CrashSequence(__null, 821); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
822 const ViewTransition* vt = aDoc->GetActiveViewTransition();
823 if (!vt) {
824 return false;
825 }
826 const auto& typeList = vt->GetTypeList();
827 if (typeList.IsEmpty()) {
828 return false;
829 }
830 for (const auto& name : *aNames) {
831 if (typeList.Contains(name.AsAtom())) {
832 // NOTE(emilio): This IsValidViewTransitionType() check is not in the spec
833 // and is rather weird, but matches other browsers for now, see:
834 // https://github.com/w3c/csswg-drafts/issues/13141
835 if (IsValidViewTransitionType(name.AsAtom())) {
836 return true;
837 }
838 }
839 }
840 return false;
841}
842
843const PreferenceSheet::Prefs* Gecko_GetPrefSheetPrefs(const Document* aDoc) {
844 return &PreferenceSheet::PrefsFor(*aDoc);
845}
846
847bool Gecko_IsTableBorderNonzero(const Element* aElement) {
848 if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
849 return false;
850 }
851 const nsAttrValue* val = aElement->GetParsedAttr(nsGkAtoms::border);
852 return val &&
853 (val->Type() != nsAttrValue::eInteger || val->GetIntegerValue() != 0);
854}
855
856bool Gecko_IsSelectListBox(const Element* aElement) {
857 const auto* select = HTMLSelectElement::FromNode(aElement);
858 return select && !select->IsCombobox();
859}
860
861bool Gecko_LookupAttrValue(const Element* aElement, nsAtom& aNamespace,
862 nsAtom& aName, nsAString& aResult) {
863 int32_t attrNameSpace = kNameSpaceID_None;
864 if (!aNamespace.IsEmpty()) {
865 attrNameSpace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
866 &aNamespace, nsContentUtils::IsChromeDoc(aElement->OwnerDoc()));
867 }
868 // All attribute names on HTML elements in HTML docs match
869 // ASCII-case-insensitively. See note in:
870 // https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute
871 if (!aName.IsAsciiLowercase() && aElement->OwnerDoc()->IsHTMLDocument() &&
872 aElement->IsHTMLElement()) {
873 RefPtr<nsAtom> lowercaseName(&aName);
874 ToLowerCaseASCII(lowercaseName);
875 return aElement->GetAttr(attrNameSpace, lowercaseName, aResult);
876 }
877 return aElement->GetAttr(attrNameSpace, &aName, aResult);
878}
879
880template <typename Implementor>
881static nsAtom* LangValue(Implementor* aElement) {
882 // TODO(emilio): Deduplicate a bit with nsIContent::GetLang().
883 const nsAttrValue* attr =
884 aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML2);
885 if (!attr && aElement->SupportsLangAttr()) {
886 attr = aElement->GetParsedAttr(nsGkAtoms::lang);
887 }
888
889 if (!attr) {
890 return nullptr;
891 }
892
893 MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attr->Type() == nsAttrValue::eAtom)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(attr->Type() == nsAttrValue::eAtom))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("attr->Type() == nsAttrValue::eAtom"
, "./../../../layout/style/GeckoBindings.cpp", 893); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "attr->Type() == nsAttrValue::eAtom" ")"
); do { MOZ_CrashSequence(__null, 893); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
894 RefPtr<nsAtom> atom = attr->GetAtomValue();
895 return atom.forget().take();
896}
897
898bool Gecko_AttrEquals(const nsAttrValue* aValue, const nsAtom* aStr,
899 bool aIgnoreCase) {
900 return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
901}
902
903bool Gecko_AttrDashEquals(const nsAttrValue* aValue, const nsAtom* aStr,
904 bool aIgnoreCase) {
905 nsAutoString str;
906 aValue->ToString(str);
907 return nsStyleUtil::DashMatchCompare(
908 str, nsDependentAtomString(aStr),
909 aIgnoreCase ? eIgnoreCase : eCaseMatters);
910}
911
912bool Gecko_AttrIncludes(const nsAttrValue* aValue, const nsAtom* aStr,
913 bool aIgnoreCase) {
914 if (aStr == nsGkAtoms::_empty) {
915 return false;
916 }
917 nsAutoString str;
918 aValue->ToString(str);
919 return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr),
920 aIgnoreCase ? eIgnoreCase : eCaseMatters);
921}
922
923bool Gecko_AttrHasSubstring(const nsAttrValue* aValue, const nsAtom* aStr,
924 bool aIgnoreCase) {
925 return aStr != nsGkAtoms::_empty &&
926 aValue->HasSubstring(nsDependentAtomString(aStr),
927 aIgnoreCase ? eIgnoreCase : eCaseMatters);
928}
929
930bool Gecko_AttrHasPrefix(const nsAttrValue* aValue, const nsAtom* aStr,
931 bool aIgnoreCase) {
932 return aStr != nsGkAtoms::_empty &&
933 aValue->HasPrefix(nsDependentAtomString(aStr),
934 aIgnoreCase ? eIgnoreCase : eCaseMatters);
935}
936
937bool Gecko_AttrHasSuffix(const nsAttrValue* aValue, const nsAtom* aStr,
938 bool aIgnoreCase) {
939 return aStr != nsGkAtoms::_empty &&
940 aValue->HasSuffix(nsDependentAtomString(aStr),
941 aIgnoreCase ? eIgnoreCase : eCaseMatters);
942}
943
944#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
945 nsAtom* prefix_##LangValue(implementor_ aElement) { \
946 return LangValue(aElement); \
947 }
948
949SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, const Element*)
950SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
951 const ServoElementSnapshot*)
952
953#undef SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS
954
955nsAtom* Gecko_Atomize(const char* aString, uint32_t aLength) {
956 nsDependentCSubstring str(aString, aLength);
957 if (NS_IsMainThread()) {
958 return NS_AtomizeMainThread(str).take();
959 }
960 return NS_Atomize(str).take();
961}
962
963nsAtom* Gecko_Atomize16(const nsAString* aString) {
964 return NS_Atomize(*aString).take();
965}
966
967void Gecko_AddRefAtom(nsAtom* aAtom) { NS_ADDREF(aAtom)(aAtom)->AddRef(); }
968
969void Gecko_ReleaseAtom(nsAtom* aAtom) { NS_RELEASE(aAtom)do { (aAtom)->Release(); (aAtom) = 0; } while (0); }
970
971void Gecko_nsFont_InitSystem(nsFont* aDest, StyleSystemFont aFontId,
972 const nsStyleFont* aFont,
973 const Document* aDocument) {
974 const nsFont& defaultVariableFont =
975 aDocument->GetFontPrefsForLang(aFont->GetLangAtom())
976 ->mDefaultVariableFont;
977
978 // We have passed uninitialized memory to this function,
979 // initialize it. We can't simply return an nsFont because then
980 // we need to know its size beforehand. Servo cannot initialize nsFont
981 // itself, so this will do.
982 new (aDest) nsFont(defaultVariableFont);
983
984 nsLayoutUtils::ComputeSystemFont(aDest, aFontId, defaultVariableFont,
985 aDocument);
986}
987
988void Gecko_nsFont_Destroy(nsFont* aDest) { aDest->~nsFont(); }
989
990StyleGenericFontFamily Gecko_nsStyleFont_ComputeFallbackFontTypeForLanguage(
991 const Document* aDoc, nsAtom* aLanguage) {
992 return aDoc->GetFontPrefsForLang(aLanguage)->GetDefaultGeneric();
993}
994
995Length Gecko_GetBaseSize(const Document* aDoc, nsAtom* aLang,
996 StyleGenericFontFamily aGeneric) {
997 return aDoc->GetFontPrefsForLang(aLang)->GetDefaultFont(aGeneric)->size;
998}
999
1000gfxFontFeatureValueSet* Gecko_ConstructFontFeatureValueSet() {
1001 return new gfxFontFeatureValueSet();
1002}
1003
1004nsTArray<uint32_t>* Gecko_AppendFeatureValueHashEntry(
1005 gfxFontFeatureValueSet* aFontFeatureValues, nsAtom* aFamily,
1006 uint32_t aAlternate, nsAtom* aName) {
1007 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1007); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1008 return aFontFeatureValues->AppendFeatureValueHashEntry(nsAtomCString(aFamily),
1009 aName, aAlternate);
1010}
1011
1012gfx::FontPaletteValueSet* Gecko_ConstructFontPaletteValueSet() {
1013 return new gfx::FontPaletteValueSet();
1014}
1015
1016gfx::FontPaletteValueSet::PaletteValues* Gecko_AppendPaletteValueHashEntry(
1017 gfx::FontPaletteValueSet* aPaletteValueSet, nsAtom* aFamily,
1018 nsAtom* aName) {
1019 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1019); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1019); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1020 return aPaletteValueSet->Insert(aName, nsAtomCString(aFamily));
1021}
1022
1023void Gecko_SetFontPaletteBase(gfx::FontPaletteValueSet::PaletteValues* aValues,
1024 int32_t aBasePaletteIndex) {
1025 aValues->mBasePalette = aBasePaletteIndex;
1026}
1027
1028void Gecko_SetFontPaletteOverride(
1029 gfx::FontPaletteValueSet::PaletteValues* aValues, int32_t aIndex,
1030 StyleAbsoluteColor* aColor) {
1031 if (aIndex < 0) {
1032 return;
1033 }
1034 aValues->mOverrides.AppendElement(gfx::FontPaletteValueSet::OverrideColor{
1035 uint32_t(aIndex), aColor->ToColor()});
1036}
1037
1038void Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
1039 nsStyleImageLayers::LayerType aLayerType) {
1040 size_t oldLength = aLayers->mLayers.Length();
1041
1042 aLayers->mLayers.EnsureLengthAtLeast(aLen);
1043
1044 for (size_t i = oldLength; i < aLen; ++i) {
1045 aLayers->mLayers[i].Initialize(aLayerType);
1046 }
1047}
1048
1049template <typename StyleType>
1050static void EnsureStyleAutoArrayLength(StyleType* aArray, size_t aLen) {
1051 aArray->EnsureLengthAtLeast(aLen);
1052}
1053
1054void Gecko_EnsureStyleAnimationArrayLength(void* aArray, size_t aLen) {
1055 auto* base = static_cast<nsStyleAutoArray<StyleAnimation>*>(aArray);
1056 EnsureStyleAutoArrayLength(base, aLen);
1057}
1058
1059void Gecko_EnsureStyleTransitionArrayLength(void* aArray, size_t aLen) {
1060 auto* base = reinterpret_cast<nsStyleAutoArray<StyleTransition>*>(aArray);
1061 EnsureStyleAutoArrayLength(base, aLen);
1062}
1063
1064void Gecko_EnsureStyleScrollTimelineArrayLength(void* aArray, size_t aLen) {
1065 auto* base = static_cast<nsStyleAutoArray<StyleScrollTimeline>*>(aArray);
1066 EnsureStyleAutoArrayLength(base, aLen);
1067}
1068
1069void Gecko_EnsureStyleViewTimelineArrayLength(void* aArray, size_t aLen) {
1070 auto* base = static_cast<nsStyleAutoArray<StyleViewTimeline>*>(aArray);
1071 EnsureStyleAutoArrayLength(base, aLen);
1072}
1073
1074// Note: There is a specialized version, FindOrInsertInitialOrFinalKeyframe(),
1075// in CSSAnimation.cpp, and it finds the matched keyframes based on the computed
1076// offset. However, this function is to find or create the matched keyframe
1077// based on the specified <keyframe-selector>, for grouping them.
1078// For more details, see the step 2.2 in
1079// https://drafts.csswg.org/css-animations-2/#keyframe-processing
1080static std::pair<Keyframe*, size_t> GetOrCreateKeyframe(
1081 nsTArray<Keyframe>* aKeyframes, StyleTimelineRangeName aRangeName,
1082 float aOffset, const StyleComputedTimingFunction* aTimingFunction,
1083 const CompositeOperationOrAuto aComposition) {
1084 MOZ_ASSERT(aKeyframes, "The keyframe array should be valid")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKeyframes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aKeyframes))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aKeyframes" " (" "The keyframe array should be valid"
")", "./../../../layout/style/GeckoBindings.cpp", 1084); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKeyframes" ") (" "The keyframe array should be valid"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1085 MOZ_ASSERT(aTimingFunction, "The timing function should be valid")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTimingFunction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTimingFunction))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aTimingFunction"
" (" "The timing function should be valid" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimingFunction"
") (" "The timing function should be valid" ")"); do { MOZ_CrashSequence
(__null, 1085); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1086 MOZ_ASSERT(aRangeName != StyleTimelineRangeName::None ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::None || (aRangeName
== StyleTimelineRangeName::None && aOffset >= 0. &&
aOffset <= 1.))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRangeName != StyleTimelineRangeName
::None || (aRangeName == StyleTimelineRangeName::None &&
aOffset >= 0. && aOffset <= 1.)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
" (" "The percentage offset should be in the range of [0.0, 1.0]"
")", "./../../../layout/style/GeckoBindings.cpp", 1089); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
") (" "The percentage offset should be in the range of [0.0, 1.0]"
")"); do { MOZ_CrashSequence(__null, 1089); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1087 (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::None || (aRangeName
== StyleTimelineRangeName::None && aOffset >= 0. &&
aOffset <= 1.))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRangeName != StyleTimelineRangeName
::None || (aRangeName == StyleTimelineRangeName::None &&
aOffset >= 0. && aOffset <= 1.)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
" (" "The percentage offset should be in the range of [0.0, 1.0]"
")", "./../../../layout/style/GeckoBindings.cpp", 1089); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
") (" "The percentage offset should be in the range of [0.0, 1.0]"
")"); do { MOZ_CrashSequence(__null, 1089); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1088 aOffset <= 1.),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::None || (aRangeName
== StyleTimelineRangeName::None && aOffset >= 0. &&
aOffset <= 1.))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRangeName != StyleTimelineRangeName
::None || (aRangeName == StyleTimelineRangeName::None &&
aOffset >= 0. && aOffset <= 1.)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
" (" "The percentage offset should be in the range of [0.0, 1.0]"
")", "./../../../layout/style/GeckoBindings.cpp", 1089); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
") (" "The percentage offset should be in the range of [0.0, 1.0]"
")"); do { MOZ_CrashSequence(__null, 1089); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1089 "The percentage offset should be in the range of [0.0, 1.0]")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::None || (aRangeName
== StyleTimelineRangeName::None && aOffset >= 0. &&
aOffset <= 1.))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRangeName != StyleTimelineRangeName
::None || (aRangeName == StyleTimelineRangeName::None &&
aOffset >= 0. && aOffset <= 1.)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
" (" "The percentage offset should be in the range of [0.0, 1.0]"
")", "./../../../layout/style/GeckoBindings.cpp", 1089); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::None || (aRangeName == StyleTimelineRangeName::None && aOffset >= 0. && aOffset <= 1.)"
") (" "The percentage offset should be in the range of [0.0, 1.0]"
")"); do { MOZ_CrashSequence(__null, 1089); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1090
1091 const auto& offset = Keyframe::OffsetType{aRangeName, (double)aOffset};
1092 size_t keyframeIndex;
1093 // We search the keyframes in the reversed order because the newest added
1094 // keyframe is the most possible one we should match (since we sorted the
1095 // keyframes with <percentage> offsets already).
1096 if (nsAnimationManager::FindMatchingKeyframe(Reversed(*aKeyframes), offset,
1097 *aTimingFunction, aComposition,
1098 keyframeIndex)) {
1099 return {&(*aKeyframes)[aKeyframes->Length() - 1 - keyframeIndex],
1100 aKeyframes->Length() - 1 - keyframeIndex};
1101 }
1102 keyframeIndex = aKeyframes->Length() - 1;
Value stored to 'keyframeIndex' is never read
1103
1104 Keyframe* keyframe = aKeyframes->AppendElement();
1105 keyframe->mOffset.emplace(offset);
1106 if (!aTimingFunction->IsLinearKeyword()) {
1107 keyframe->mTimingFunction.emplace(*aTimingFunction);
1108 }
1109 keyframe->mComposite = aComposition;
1110 // Return the length of aKeyframes to represent the new Keyframe is inserted.
1111 return {keyframe, aKeyframes->Length()};
1112}
1113
1114Keyframe* Gecko_GetOrCreateKeyframeForPercentageOffset(
1115 nsTArray<Keyframe>* aKeyframes, float aOffset,
1116 const StyleComputedTimingFunction* aTimingFunction,
1117 const CompositeOperationOrAuto aComposition) {
1118 MOZ_ASSERT(aKeyframes->IsEmpty() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKeyframes->IsEmpty() || aKeyframes->LastElement
().mOffset->mPercentage >= aOffset)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aKeyframes->IsEmpty() || aKeyframes
->LastElement().mOffset->mPercentage >= aOffset))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
" (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
") (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")"); do
{ MOZ_CrashSequence(__null, 1121); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1119 aKeyframes->LastElement().mOffset->mPercentage >= aOffset,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKeyframes->IsEmpty() || aKeyframes->LastElement
().mOffset->mPercentage >= aOffset)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aKeyframes->IsEmpty() || aKeyframes
->LastElement().mOffset->mPercentage >= aOffset))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
" (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
") (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")"); do
{ MOZ_CrashSequence(__null, 1121); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1120 "The percentage offset should be less than or equal to the last "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKeyframes->IsEmpty() || aKeyframes->LastElement
().mOffset->mPercentage >= aOffset)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aKeyframes->IsEmpty() || aKeyframes
->LastElement().mOffset->mPercentage >= aOffset))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
" (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
") (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")"); do
{ MOZ_CrashSequence(__null, 1121); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1121 "keyframe's offset if there are exisiting keyframes")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKeyframes->IsEmpty() || aKeyframes->LastElement
().mOffset->mPercentage >= aOffset)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aKeyframes->IsEmpty() || aKeyframes
->LastElement().mOffset->mPercentage >= aOffset))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
" (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyframes->IsEmpty() || aKeyframes->LastElement().mOffset->mPercentage >= aOffset"
") (" "The percentage offset should be less than or equal to the last "
"keyframe's offset if there are exisiting keyframes" ")"); do
{ MOZ_CrashSequence(__null, 1121); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1122 return GetOrCreateKeyframe(aKeyframes, StyleTimelineRangeName::None, aOffset,
1123 aTimingFunction, aComposition)
1124 .first;
1125}
1126
1127Keyframe* Gecko_GetOrCreateKeyframeForTimelineRangeOffset(
1128 nsTArray<Keyframe>* aKeyframes, const StyleTimelineRangeName aRangeName,
1129 float aOffset, const StyleComputedTimingFunction* aTimingFunction,
1130 const CompositeOperationOrAuto aComposition, size_t* aMatchedIdx) {
1131 MOZ_ASSERT(aRangeName != StyleTimelineRangeName::Normal,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::Normal)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRangeName != StyleTimelineRangeName::Normal))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::Normal"
" (" "normal shouldn't be used" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::Normal"
") (" "normal shouldn't be used" ")"); do { MOZ_CrashSequence
(__null, 1132); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1132 "normal shouldn't be used")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRangeName != StyleTimelineRangeName::Normal)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRangeName != StyleTimelineRangeName::Normal))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aRangeName != StyleTimelineRangeName::Normal"
" (" "normal shouldn't be used" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRangeName != StyleTimelineRangeName::Normal"
") (" "normal shouldn't be used" ")"); do { MOZ_CrashSequence
(__null, 1132); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1133 auto [keyframe, idx] = GetOrCreateKeyframe(aKeyframes, aRangeName, aOffset,
1134 aTimingFunction, aComposition);
1135 *aMatchedIdx = idx;
1136 return keyframe;
1137}
1138
1139void Gecko_GetComputedURLSpec(const StyleComputedUrl* aURL, nsCString* aOut) {
1140 MOZ_ASSERT(aURL)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURL)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURL))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURL", "./../../../layout/style/GeckoBindings.cpp"
, 1140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURL" ")");
do { MOZ_CrashSequence(__null, 1140); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1141 MOZ_ASSERT(aOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOut)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aOut))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aOut", "./../../../layout/style/GeckoBindings.cpp"
, 1141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOut" ")");
do { MOZ_CrashSequence(__null, 1141); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1142 if (aURL->IsLocalRef()) {
1143 aOut->Assign(aURL->SpecifiedSerialization());
1144 return;
1145 }
1146
1147 if (nsIURI* uri = aURL->GetURI()) {
1148 nsresult rv = uri->GetSpec(*aOut);
1149 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1150 return;
1151 }
1152 }
1153
1154 // Empty URL computes to empty, per spec:
1155 if (aURL->SpecifiedSerialization().IsEmpty()) {
1156 aOut->Truncate();
1157 } else {
1158 aOut->AssignLiteral("about:invalid");
1159 }
1160}
1161
1162bool Gecko_IsSupportedImageMimeType(const uint8_t* aMimeType,
1163 const uint32_t aLen) {
1164 nsDependentCSubstring mime(reinterpret_cast<const char*>(aMimeType), aLen);
1165 return imgLoader::SupportImageWithMimeType(
1166 mime, AcceptedMimeTypes::IMAGES_AND_DOCUMENTS);
1167}
1168
1169void Gecko_nsIURI_Debug(nsIURI* aURI, nsCString* aOut) {
1170 // TODO(emilio): Do we have more useful stuff to put here, maybe?
1171 if (aURI) {
1172 *aOut = aURI->GetSpecOrDefault();
1173 }
1174}
1175
1176// XXX Implemented by hand because even though it's thread-safe, only the
1177// subclasses have the HasThreadSafeRefCnt bits.
1178void Gecko_AddRefnsIURIArbitraryThread(nsIURI* aPtr) { NS_ADDREF(aPtr)(aPtr)->AddRef(); }
1179void Gecko_ReleasensIURIArbitraryThread(nsIURI* aPtr) { NS_RELEASE(aPtr)do { (aPtr)->Release(); (aPtr) = 0; } while (0); }
1180
1181void Gecko_nsIReferrerInfo_Debug(nsIReferrerInfo* aReferrerInfo,
1182 nsCString* aOut) {
1183 if (aReferrerInfo) {
1184 if (nsCOMPtr<nsIURI> referrer = aReferrerInfo->GetComputedReferrer()) {
1185 *aOut = referrer->GetSpecOrDefault();
1186 }
1187 }
1188}
1189
1190template <typename ElementLike>
1191void DebugListAttributes(const ElementLike& aElement, nsCString& aOut) {
1192 const uint32_t kMaxAttributeLength = 40;
1193
1194 uint32_t i = 0;
1195 while (BorrowedAttrInfo info = aElement.GetAttrInfoAt(i++)) {
1196 aOut.AppendLiteral(" ");
1197 if (nsAtom* prefix = info.mName->GetPrefix()) {
1198 aOut.Append(NS_ConvertUTF16toUTF8(nsDependentAtomString(prefix)));
1199 aOut.AppendLiteral(":");
1200 }
1201 aOut.Append(
1202 NS_ConvertUTF16toUTF8(nsDependentAtomString(info.mName->LocalName())));
1203 if (!info.mValue) {
1204 continue;
1205 }
1206 aOut.AppendLiteral("=\"");
1207 nsAutoString value;
1208 info.mValue->ToString(value);
1209 if (value.Length() > kMaxAttributeLength) {
1210 value.Truncate(kMaxAttributeLength - 3);
1211 value.AppendLiteral("...");
1212 }
1213 aOut.Append(NS_ConvertUTF16toUTF8(value));
1214 aOut.AppendLiteral("\"");
1215 }
1216}
1217
1218void Gecko_Element_DebugListAttributes(const Element* aElement,
1219 nsCString* aOut) {
1220 DebugListAttributes(*aElement, *aOut);
1221}
1222
1223void Gecko_Snapshot_DebugListAttributes(const ServoElementSnapshot* aSnapshot,
1224 nsCString* aOut) {
1225 DebugListAttributes(*aSnapshot, *aOut);
1226}
1227
1228NS_IMPL_THREADSAFE_FFI_REFCOUNTING(URLExtraData, URLExtraData)static_assert(URLExtraData::HasThreadSafeRefCnt::value, "NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with "
"classes that have thread-safe refcounting"); void Gecko_AddRefURLExtraDataArbitraryThread
(URLExtraData* aPtr) { (aPtr)->AddRef(); } void Gecko_ReleaseURLExtraDataArbitraryThread
(URLExtraData* aPtr) { do { (aPtr)->Release(); (aPtr) = 0;
} while (0); }
;
1229
1230bool Gecko_IsURIInList(const URLExtraData* aData, const nsACString* aList) {
1231 return nsContentUtils::IsURIInList(aData->BaseURI(),
1232 PromiseFlatCStringTPromiseFlatString<char>(*aList));
1233}
1234
1235Length Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont,
1236 const Document* aDocument) {
1237 // Don't change font-size:0, since that would un-hide hidden text.
1238 if (aFont->mSize.IsZero()) {
1239 return {0};
1240 }
1241 // Don't change it for docs where we don't enable the min-font-size.
1242 if (!aFont->MinFontSizeEnabled()) {
1243 return {0};
1244 }
1245 Length minFontSize =
1246 aDocument->GetFontPrefsForLang(aFont->GetLangAtom())->mMinimumFontSize;
1247 if (minFontSize.ToCSSPixels() <= 0.0f) {
1248 return {0};
1249 }
1250 minFontSize.ScaleBy(aFont->mMinFontSizeRatio._0);
1251 return minFontSize;
1252}
1253
1254static StaticRefPtr<UACacheReporter> gUACacheReporter;
1255
1256namespace mozilla {
1257
1258void InitializeServo() {
1259 URLExtraData::Init();
1260 Servo_Initialize(URLExtraData::Dummy(), URLExtraData::DummyChrome());
1261
1262 gUACacheReporter = new UACacheReporter();
1263 RegisterWeakMemoryReporter(gUACacheReporter);
1264
1265 sServoFFILock = new Mutex("Servo::FFILock");
1266}
1267
1268void ShutdownServo() {
1269 MOZ_ASSERT(sServoFFILock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sServoFFILock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sServoFFILock))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("sServoFFILock",
"./../../../layout/style/GeckoBindings.cpp", 1269); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sServoFFILock" ")"); do { MOZ_CrashSequence
(__null, 1269); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1270
1271 UnregisterWeakMemoryReporter(gUACacheReporter);
1272 gUACacheReporter = nullptr;
1273
1274 sServoFFILock = nullptr;
1275 Servo_Shutdown();
1276
1277 URLExtraData::Shutdown();
1278}
1279
1280void AssertIsMainThreadOrServoFontMetricsLocked() {
1281 if (!NS_IsMainThread()) {
1282 MOZ_ASSERT(sServoFFILock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sServoFFILock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sServoFFILock))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("sServoFFILock",
"./../../../layout/style/GeckoBindings.cpp", 1282); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sServoFFILock" ")"); do { MOZ_CrashSequence
(__null, 1282); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1283 sServoFFILock->AssertCurrentThreadOwns();
1284 }
1285}
1286
1287} // namespace mozilla
1288
1289GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext* aPresContext,
1290 bool aIsVertical,
1291 const nsStyleFont* aFont,
1292 Length aFontSize,
1293 StyleQueryFontMetricsFlags flags) {
1294 MutexAutoLock guard(*sServoFFILock);
1295
1296 // Getting font metrics can require some main thread only work to be
1297 // done, such as work that needs to touch non-threadsafe refcounted
1298 // objects (like the DOM FontFace/FontFaceSet objects), network loads, etc.
1299 //
1300 // To handle this work, font code checks whether we are in a Servo traversal
1301 // and if so, appends PostTraversalTasks to the current ServoStyleSet
1302 // to be performed immediately after the traversal is finished. This
1303 // works well for starting downloadable font loads, since we don't have
1304 // those fonts available to get metrics for anyway. Platform fonts and
1305 // ArrayBuffer-backed FontFace objects are handled synchronously.
1306
1307 nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
1308 RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor(
1309 presContext, aIsVertical, aFont, aFontSize,
1310 bool(flags & StyleQueryFontMetricsFlags::USE_USER_FONT_SET));
1311 auto* fontGroup = fm->GetThebesFontGroup();
1312 auto metrics = fontGroup->GetMetricsForCSSUnits(fm->Orientation(), flags);
1313
1314 float scriptPercentScaleDown = 0;
1315 float scriptScriptPercentScaleDown = 0;
1316 if (flags & StyleQueryFontMetricsFlags::NEEDS_MATH_SCALES) {
1317 RefPtr<gfxFont> font = fontGroup->GetFirstValidFont();
1318 if (font->TryGetMathTable()) {
1319 scriptPercentScaleDown = static_cast<float>(
1320 font->MathTable()->Constant(gfxMathTable::ScriptPercentScaleDown));
1321 scriptScriptPercentScaleDown =
1322 static_cast<float>(font->MathTable()->Constant(
1323 gfxMathTable::ScriptScriptPercentScaleDown));
1324 }
1325 }
1326
1327 int32_t d2a = aPresContext->AppUnitsPerDevPixel();
1328 auto ToLength = [](nscoord aLen) {
1329 return Length::FromPixels(CSSPixel::FromAppUnits(aLen));
1330 };
1331 return {ToLength(NS_round(metrics.xHeight * d2a)),
1332 ToLength(NS_round(metrics.zeroWidth * d2a)),
1333 ToLength(NS_round(metrics.capHeight * d2a)),
1334 ToLength(NS_round(metrics.ideographicWidth * d2a)),
1335 ToLength(NS_round(metrics.maxAscent * d2a)),
1336 ToLength(NS_round(fontGroup->GetStyle()->size * d2a)),
1337 scriptPercentScaleDown,
1338 scriptScriptPercentScaleDown};
1339}
1340
1341NS_IMPL_THREADSAFE_FFI_REFCOUNTING(SheetLoadDataHolder, SheetLoadDataHolder)static_assert(SheetLoadDataHolder::HasThreadSafeRefCnt::value
, "NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with "
"classes that have thread-safe refcounting"); void Gecko_AddRefSheetLoadDataHolderArbitraryThread
(SheetLoadDataHolder* aPtr) { (aPtr)->AddRef(); } void Gecko_ReleaseSheetLoadDataHolderArbitraryThread
(SheetLoadDataHolder* aPtr) { do { (aPtr)->Release(); (aPtr
) = 0; } while (0); }
;
1342
1343void Gecko_StyleSheet_FinishAsyncParse(
1344 SheetLoadDataHolder* aData,
1345 StyleStrong<StyleStylesheetContents> aSheetContents) {
1346 RefPtr<SheetLoadDataHolder> loadData = aData;
1347 RefPtr<StyleStylesheetContents> sheetContents = aSheetContents.Consume();
1348 NS_DispatchToMainThreadQueue(
1349 NS_NewRunnableFunction(__func__,
1350 [d = std::move(loadData),
1351 contents = std::move(sheetContents)]() mutable {
1352 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1352); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1352); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1353 SheetLoadData* data = d->get();
1354 data->mSheet->FinishAsyncParse(
1355 contents.forget());
1356 }),
1357 EventQueuePriority::RenderBlocking);
1358}
1359
1360static already_AddRefed<StyleSheet> LoadImportSheet(
1361 Loader* aLoader, StyleSheet* aParent, SheetLoadData* aParentLoadData,
1362 LoaderReusableStyleSheets* aReusableSheets, const StyleCssUrl& aURL,
1363 already_AddRefed<StyleLockedMediaList> aMediaList) {
1364 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1364); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1364); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1365 MOZ_ASSERT(aLoader, "Should've catched this before")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoader))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoader" " (" "Should've catched this before"
")", "./../../../layout/style/GeckoBindings.cpp", 1365); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoader" ") (" "Should've catched this before"
")"); do { MOZ_CrashSequence(__null, 1365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1366 MOZ_ASSERT(aParent, "Only used for @import, so parent should exist!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent" " (" "Only used for @import, so parent should exist!"
")", "./../../../layout/style/GeckoBindings.cpp", 1366); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent" ") (" "Only used for @import, so parent should exist!"
")"); do { MOZ_CrashSequence(__null, 1366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1367
1368 auto media = MakeRefPtr<MediaList>(std::move(aMediaList));
1369 nsCOMPtr<nsIURI> uri = aURL.GetURI();
1370 nsresult rv = uri ? NS_OK : NS_ERROR_FAILURE;
1371
1372 size_t previousSheetCount = aParent->ChildSheets().Length();
1373 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1374 // TODO(emilio): We should probably make LoadChildSheet return the
1375 // stylesheet rather than the return code.
1376 rv = aLoader->LoadChildSheet(*aParent, aParentLoadData, uri, media,
1377 aReusableSheets);
1378 }
1379
1380 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || previousSheetCount == aParent->ChildSheets().Length()) {
1381 // Servo and Gecko have different ideas of what a valid URL is, so we might
1382 // get in here with a URL string that NS_NewURI can't handle. We may also
1383 // reach here via an import cycle. For the import cycle case, we need some
1384 // sheet object per spec, even if its empty. DevTools uses the URI to
1385 // realize it has hit an import cycle, so we mark it complete to make the
1386 // sheet readable from JS.
1387 RefPtr<StyleSheet> emptySheet =
1388 aParent->CreateEmptyChildSheet(media.forget());
1389 // Make a dummy URI if we don't have one because some methods assume
1390 // non-null URIs.
1391 if (!uri) {
1392 NS_NewURI(getter_AddRefs(uri), "about:invalid"_ns);
1393 }
1394 nsCOMPtr<nsIReferrerInfo> referrerInfo =
1395 ReferrerInfo::CreateForExternalCSSResources(emptySheet, uri);
1396 emptySheet->SetURIs(uri, uri, referrerInfo, aURL.ExtraData().Principal());
1397 emptySheet->SetComplete();
1398 aParent->AppendStyleSheet(*emptySheet);
1399 return emptySheet.forget();
1400 }
1401
1402 RefPtr<StyleSheet> sheet = aParent->ChildSheets().LastElement();
1403 return sheet.forget();
1404}
1405
1406StyleSheet* Gecko_LoadStyleSheet(Loader* aLoader, StyleSheet* aParent,
1407 SheetLoadData* aParentLoadData,
1408 LoaderReusableStyleSheets* aReusableSheets,
1409 const StyleCssUrl* aUrl,
1410 StyleStrong<StyleLockedMediaList> aMediaList) {
1411 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1411); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1411); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1412 MOZ_ASSERT(aUrl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aUrl)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aUrl))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aUrl", "./../../../layout/style/GeckoBindings.cpp"
, 1412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aUrl" ")");
do { MOZ_CrashSequence(__null, 1412); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1413
1414 return LoadImportSheet(aLoader, aParent, aParentLoadData, aReusableSheets,
1415 *aUrl, aMediaList.Consume())
1416 .take();
1417}
1418
1419void Gecko_LoadStyleSheetAsync(SheetLoadDataHolder* aParentData,
1420 const StyleCssUrl* aUrl,
1421 StyleStrong<StyleLockedMediaList> aMediaList,
1422 StyleStrong<StyleLockedImportRule> aImportRule) {
1423 MOZ_ASSERT(aUrl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aUrl)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aUrl))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aUrl", "./../../../layout/style/GeckoBindings.cpp"
, 1423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aUrl" ")");
do { MOZ_CrashSequence(__null, 1423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1424 RefPtr<SheetLoadDataHolder> loadData = aParentData;
1425 RefPtr<StyleLockedMediaList> mediaList = aMediaList.Consume();
1426 RefPtr<StyleLockedImportRule> importRule = aImportRule.Consume();
1427 NS_DispatchToMainThreadQueue(
1428 NS_NewRunnableFunction(
1429 __func__,
1430 [data = std::move(loadData), url = StyleCssUrl(*aUrl),
1431 media = std::move(mediaList),
1432 import = std::move(importRule)]() mutable {
1433 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1433); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1433); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1434 SheetLoadData* d = data->get();
1435 RefPtr<StyleSheet> sheet = LoadImportSheet(
1436 d->mLoader, d->mSheet, d, nullptr, url, media.forget());
1437 Servo_ImportRule_SetSheet(import, sheet);
1438 }),
1439 EventQueuePriority::RenderBlocking);
1440}
1441
1442void Gecko_AddPropertyToSet(nsCSSPropertyIDSet* aPropertySet,
1443 NonCustomCSSPropertyId aProperty) {
1444 aPropertySet->AddProperty(aProperty);
1445}
1446
1447bool Gecko_DocumentRule_UseForPresentation(
1448 const Document* aDocument, const nsACString* aPattern,
1449 DocumentMatchingFunction aMatchingFunction) {
1450 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1450); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1450); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1451
1452 nsIURI* docURI = aDocument->GetDocumentURI();
1453 nsAutoCString docURISpec;
1454 if (docURI) {
1455 // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
1456 nsresult rv = docURI->GetSpec(docURISpec);
1457 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../layout/style/GeckoBindings.cpp"
, 1457); return false; } } while (false)
;
1458 }
1459
1460 return CSSMozDocumentRule::Match(aDocument, docURI, docURISpec, *aPattern,
1461 aMatchingFunction);
1462}
1463
1464void Gecko_SetJemallocThreadLocalArena(bool enabled) {
1465#if defined(MOZ_MEMORY1)
1466 jemalloc_thread_local_arena(enabled);
1467#endif
1468}
1469
1470template <typename T>
1471void Construct(T* aPtr, const Document* aDoc) {
1472 if constexpr (std::is_constructible_v<T, const Document&>) {
1473 MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc", "./../../../layout/style/GeckoBindings.cpp"
, 1473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")");
do { MOZ_CrashSequence(__null, 1473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1474 new (KnownNotNull, aPtr) T(*aDoc);
1475 } else {
1476 MOZ_ASSERT(!aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aDoc)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!aDoc))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!aDoc", "./../../../layout/style/GeckoBindings.cpp"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aDoc" ")")
; do { MOZ_CrashSequence(__null, 1476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1477 new (KnownNotNull, aPtr) T();
1478 // These instance are intentionally global, and we don't want leakcheckers
1479 // to report them.
1480 aPtr->MarkLeaked();
1481 }
1482}
1483
1484#define GENERATE_GECKO_FUNCTIONS(name) \
1485 void Gecko_Construct_Default_nsStyle##name(nsStyle##name* ptr, \
1486 const Document* doc) { \
1487 Construct(ptr, doc); \
1488 } \
1489 void Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr, \
1490 const nsStyle##name* other) { \
1491 new (ptr) nsStyle##name(*other); \
1492 } \
1493 void Gecko_Destroy_nsStyle##name(nsStyle##name* ptr) { \
1494 ptr->~nsStyle##name(); \
1495 }
1496
1497FOR_EACH_STYLE_STRUCT(GENERATE_GECKO_FUNCTIONS, GENERATE_GECKO_FUNCTIONS)GENERATE_GECKO_FUNCTIONS(Font) GENERATE_GECKO_FUNCTIONS(List)
GENERATE_GECKO_FUNCTIONS(Text) GENERATE_GECKO_FUNCTIONS(Visibility
) GENERATE_GECKO_FUNCTIONS(UI) GENERATE_GECKO_FUNCTIONS(TableBorder
) GENERATE_GECKO_FUNCTIONS(SVG) GENERATE_GECKO_FUNCTIONS(Background
) GENERATE_GECKO_FUNCTIONS(Position) GENERATE_GECKO_FUNCTIONS
(TextReset) GENERATE_GECKO_FUNCTIONS(Display) GENERATE_GECKO_FUNCTIONS
(Content) GENERATE_GECKO_FUNCTIONS(UIReset) GENERATE_GECKO_FUNCTIONS
(Table) GENERATE_GECKO_FUNCTIONS(Margin) GENERATE_GECKO_FUNCTIONS
(Padding) GENERATE_GECKO_FUNCTIONS(Border) GENERATE_GECKO_FUNCTIONS
(Outline) GENERATE_GECKO_FUNCTIONS(XUL) GENERATE_GECKO_FUNCTIONS
(SVGReset) GENERATE_GECKO_FUNCTIONS(Column) GENERATE_GECKO_FUNCTIONS
(Effects) GENERATE_GECKO_FUNCTIONS(Page)
1498
1499#undef GENERATE_GECKO_FUNCTIONS
1500
1501bool Gecko_ErrorReportingEnabled(const StyleSheet* aSheet,
1502 const Loader* aLoader,
1503 uint64_t* aOutWindowId) {
1504 if (!ErrorReporter::ShouldReportErrors(aSheet, aLoader)) {
1505 return false;
1506 }
1507 *aOutWindowId = ErrorReporter::FindInnerWindowId(aSheet, aLoader);
1508 return true;
1509}
1510
1511void Gecko_ReportUnexpectedCSSError(const uint64_t aWindowId, nsIURI* aURI,
1512 const char* message, const char* param,
1513 uint32_t paramLen, const char* prefix,
1514 const char* prefixParam,
1515 uint32_t prefixParamLen, const char* suffix,
1516 const char* selectors,
1517 uint32_t selectorsLen, uint32_t lineNumber,
1518 uint32_t colNumber) {
1519 MOZ_RELEASE_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1519); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1519); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1520
1521 ErrorReporter reporter(aWindowId);
1522
1523 if (prefix) {
1524 if (prefixParam) {
1525 nsDependentCSubstring paramValue(prefixParam, prefixParamLen);
1526 AutoTArray<nsString, 1> wideParam;
1527 CopyUTF8toUTF16(paramValue, *wideParam.AppendElement());
1528 reporter.ReportUnexpectedUnescaped(prefix, wideParam);
1529 } else {
1530 reporter.ReportUnexpected(prefix);
1531 }
1532 }
1533
1534 if (param) {
1535 nsDependentCSubstring paramValue(param, paramLen);
1536 AutoTArray<nsString, 1> wideParam;
1537 CopyUTF8toUTF16(paramValue, *wideParam.AppendElement());
1538 reporter.ReportUnexpectedUnescaped(message, wideParam);
1539 } else {
1540 reporter.ReportUnexpected(message);
1541 }
1542
1543 if (suffix) {
1544 reporter.ReportUnexpected(suffix);
1545 }
1546 nsDependentCSubstring selectorsValue(selectors, selectorsLen);
1547 reporter.OutputError(selectorsValue, lineNumber + 1, colNumber, aURI);
1548}
1549
1550void Gecko_ContentList_AppendAll(SimpleContentList* aList,
1551 const Element** aElements, size_t aLength) {
1552 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1552); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1552); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1553 MOZ_ASSERT(aElements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElements)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElements))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElements", "./../../../layout/style/GeckoBindings.cpp"
, 1553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElements" ")"
); do { MOZ_CrashSequence(__null, 1553); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1554 MOZ_ASSERT(aLength)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLength)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLength))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLength", "./../../../layout/style/GeckoBindings.cpp"
, 1554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLength" ")"
); do { MOZ_CrashSequence(__null, 1554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1555 MOZ_ASSERT(aList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aList)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aList))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aList", "./../../../layout/style/GeckoBindings.cpp"
, 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aList" ")")
; do { MOZ_CrashSequence(__null, 1555); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1556
1557 aList->SetCapacity(aLength);
1558
1559 for (size_t i = 0; i < aLength; ++i) {
1560 aList->AppendElement(const_cast<Element*>(aElements[i]));
1561 }
1562}
1563
1564RustSpan<const Element* const> Gecko_Document_GetElementsWithId(
1565 const Document* aDoc, nsAtom* aId) {
1566 MOZ_ASSERT(aDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aDoc", "./../../../layout/style/GeckoBindings.cpp"
, 1566); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDoc" ")");
do { MOZ_CrashSequence(__null, 1566); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1567 MOZ_ASSERT(aId)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aId)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aId))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aId", "./../../../layout/style/GeckoBindings.cpp"
, 1567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aId" ")"); do
{ MOZ_CrashSequence(__null, 1567); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1568 auto span = aDoc->GetAllElementsForId(aId);
1569 return {span.Elements(), span.Length()};
1570}
1571
1572RustSpan<const Element* const> Gecko_ShadowRoot_GetElementsWithId(
1573 const ShadowRoot* aShadowRoot, nsAtom* aId) {
1574 MOZ_ASSERT(aShadowRoot)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aShadowRoot)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aShadowRoot))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aShadowRoot", "./../../../layout/style/GeckoBindings.cpp"
, 1574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aShadowRoot"
")"); do { MOZ_CrashSequence(__null, 1574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1575 MOZ_ASSERT(aId)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aId)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aId))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aId", "./../../../layout/style/GeckoBindings.cpp"
, 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aId" ")"); do
{ MOZ_CrashSequence(__null, 1575); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1576 auto span = aShadowRoot->GetAllElementsForId(aId);
1577 return {span.Elements(), span.Length()};
1578}
1579
1580static StyleComputedMozPrefFeatureValue GetPrefValue(const nsCString& aPref) {
1581 using Value = StyleComputedMozPrefFeatureValue;
1582 switch (Preferences::GetType(aPref.get())) {
1583 case nsIPrefBranch::PREF_STRING: {
1584 nsAutoString value;
1585 Preferences::GetString(aPref.get(), value);
1586 return Value::String(StyleAtomString{NS_Atomize(value)});
1587 }
1588 case nsIPrefBranch::PREF_INT:
1589 return Value::Integer(Preferences::GetInt(aPref.get(), 0));
1590 case nsIPrefBranch::PREF_BOOL: {
1591 auto value = Preferences::GetBool(aPref.get(), false)
1592 ? StyleBoolValue::True
1593 : StyleBoolValue::False;
1594 return Value::Boolean(value);
1595 }
1596 case nsIPrefBranch::PREF_INVALID:
1597 default:
1598 break;
1599 }
1600
1601 return StyleComputedMozPrefFeatureValue::None();
1602}
1603
1604bool Gecko_EvalMozPrefFeature(nsAtom* aPref,
1605 const StyleComputedMozPrefFeatureValue* aValue) {
1606 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../layout/style/GeckoBindings.cpp", 1606); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1606); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1607 MOZ_ASSERT(aValue)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aValue)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aValue))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aValue", "./../../../layout/style/GeckoBindings.cpp"
, 1607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aValue" ")"
); do { MOZ_CrashSequence(__null, 1607); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1608 using Value = StyleComputedMozPrefFeatureValue;
1609 using PrefMap = nsTHashMap<RefPtr<nsAtom>, Value>;
1610 // This map leaks until shutdown, but that's fine, all the values are
1611 // controlled by us so it's not expected to be big.
1612 static StaticAutoPtr<PrefMap> sRegisteredPrefs;
1613 if (!sRegisteredPrefs) {
1614 if (PastShutdownPhase(ShutdownPhase::XPCOMShutdownFinal)) {
1615 // Styling doesn't really matter much at this point, don't bother.
1616 return false;
1617 }
1618 sRegisteredPrefs = new PrefMap();
1619 ClearOnShutdown(&sRegisteredPrefs);
1620 }
1621
1622 const auto& value = sRegisteredPrefs->LookupOrInsertWith(aPref, [&] {
1623 nsAutoAtomCString prefName(aPref);
1624 Preferences::RegisterCallback(
1625 [](const char* aPrefName, void*) {
1626 nsDependentCString name(aPrefName);
1627 if (sRegisteredPrefs) {
1628 RefPtr<nsAtom> nameAtom = NS_Atomize(name);
1629 sRegisteredPrefs->InsertOrUpdate(nameAtom, GetPrefValue(name));
1630 }
1631 LookAndFeel::NotifyChangedAllWindows(
1632 widget::ThemeChangeKind::MediaQueriesOnly);
1633 },
1634 prefName);
1635 return GetPrefValue(prefName);
1636 });
1637 if (aValue->IsNone()) {
1638 // For a non-specified query, we return true if the pref is not false, zero,
1639 // empty or invalid
1640 switch (value.tag) {
1641 case Value::Tag::None:
1642 return false;
1643 case Value::Tag::Boolean:
1644 return value.AsBoolean() == StyleBoolValue::True;
1645 case Value::Tag::Integer:
1646 return value.AsInteger() != 0;
1647 case Value::Tag::String:
1648 return !value.AsString().AsAtom()->IsEmpty();
1649 }
1650 return false;
1651 }
1652 return value == *aValue;
1653}
1654
1655bool Gecko_IsFontFormatSupported(StyleFontFaceSourceFormatKeyword aFormat) {
1656 return gfxPlatform::GetPlatform()->IsFontFormatSupported(
1657 aFormat, StyleFontFaceSourceTechFlags::Empty());
1658}
1659
1660bool Gecko_IsFontTechSupported(StyleFontFaceSourceTechFlags aFlag) {
1661 return gfxPlatform::GetPlatform()->IsFontFormatSupported(
1662 StyleFontFaceSourceFormatKeyword::None, aFlag);
1663}
1664
1665bool Gecko_IsKnownIconFontFamily(const nsAtom* aFamilyName) {
1666 return gfxPlatform::GetPlatform()->IsKnownIconFontFamily(aFamilyName);
1667}
1668
1669bool Gecko_IsInServoTraversal() { return ServoStyleSet::IsInServoTraversal(); }
1670
1671bool Gecko_IsMainThread() { return NS_IsMainThread(); }
1672
1673bool Gecko_IsDOMWorkerThread() { return !!GetCurrentThreadWorkerPrivate(); }
1674
1675int32_t Gecko_GetNumStyleThreads() {
1676 if (const auto& cpuInfo = hal::GetHeterogeneousCpuInfo()) {
1677 size_t numBigCpus = cpuInfo->mBigCpus.Count();
1678 // If CPUs are homogeneous we do not need to override stylo's
1679 // default number of threads.
1680 if (numBigCpus != cpuInfo->mTotalNumCpus) {
1681 // From testing on a variety of devices it appears using only
1682 // the number of big cores gives best performance when there are
1683 // 2 or more big cores. If there are fewer than 2 big cores then
1684 // additionally using the medium cores performs better.
1685 if (numBigCpus >= 2) {
1686 return static_cast<int32_t>(numBigCpus);
1687 }
1688 return static_cast<int32_t>(numBigCpus + cpuInfo->mMediumCpus.Count());
1689 }
1690 }
1691
1692 return -1;
1693}
1694
1695const nsAttrValue* Gecko_GetSVGAnimatedClass(const Element* aElement) {
1696 MOZ_ASSERT(aElement->IsSVGElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement->IsSVGElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement->IsSVGElement())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement->IsSVGElement()"
, "./../../../layout/style/GeckoBindings.cpp", 1696); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElement->IsSVGElement()" ")"); do { MOZ_CrashSequence
(__null, 1696); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1697 return static_cast<const SVGElement*>(aElement)->GetAnimatedClassName();
1698}
1699
1700bool Gecko_AssertClassAttrValueIsSane(const nsAttrValue* aValue) {
1701 MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aValue->Type() == nsAttrValue::eAtom || aValue->
Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue
::eAtomArray)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aValue->Type() == nsAttrValue::
eAtom || aValue->Type() == nsAttrValue::eString || aValue->
Type() == nsAttrValue::eAtomArray))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
, "./../../../layout/style/GeckoBindings.cpp", 1703); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
")"); do { MOZ_CrashSequence(__null, 1703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1702 aValue->Type() == nsAttrValue::eString ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aValue->Type() == nsAttrValue::eAtom || aValue->
Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue
::eAtomArray)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aValue->Type() == nsAttrValue::
eAtom || aValue->Type() == nsAttrValue::eString || aValue->
Type() == nsAttrValue::eAtomArray))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
, "./../../../layout/style/GeckoBindings.cpp", 1703); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
")"); do { MOZ_CrashSequence(__null, 1703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1703 aValue->Type() == nsAttrValue::eAtomArray)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aValue->Type() == nsAttrValue::eAtom || aValue->
Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue
::eAtomArray)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aValue->Type() == nsAttrValue::
eAtom || aValue->Type() == nsAttrValue::eString || aValue->
Type() == nsAttrValue::eAtomArray))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
, "./../../../layout/style/GeckoBindings.cpp", 1703); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aValue->Type() == nsAttrValue::eAtom || aValue->Type() == nsAttrValue::eString || aValue->Type() == nsAttrValue::eAtomArray"
")"); do { MOZ_CrashSequence(__null, 1703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1704 MOZ_ASSERT_IF(do { if (aValue->Type() == nsAttrValue::eString) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(nsContentUtils
::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue
->GetStringValue()) .IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue
()) .IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
, "./../../../layout/style/GeckoBindings.cpp", 1708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1705 aValue->Type() == nsAttrValue::eString,do { if (aValue->Type() == nsAttrValue::eString) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(nsContentUtils
::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue
->GetStringValue()) .IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue
()) .IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
, "./../../../layout/style/GeckoBindings.cpp", 1708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1706 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(do { if (aValue->Type() == nsAttrValue::eString) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(nsContentUtils
::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue
->GetStringValue()) .IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue
()) .IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
, "./../../../layout/style/GeckoBindings.cpp", 1708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1707 aValue->GetStringValue())do { if (aValue->Type() == nsAttrValue::eString) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(nsContentUtils
::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue
->GetStringValue()) .IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue
()) .IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
, "./../../../layout/style/GeckoBindings.cpp", 1708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1708 .IsEmpty())do { if (aValue->Type() == nsAttrValue::eString) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(nsContentUtils
::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue
->GetStringValue()) .IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue
()) .IsEmpty()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
, "./../../../layout/style/GeckoBindings.cpp", 1708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( aValue->GetStringValue()) .IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1709 return true;
1710}
1711
1712void Gecko_GetSafeAreaInsets(const nsPresContext* aPresContext, float* aTop,
1713 float* aRight, float* aBottom, float* aLeft) {
1714 MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext", "./../../../layout/style/GeckoBindings.cpp"
, 1714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 1714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1715 const CSSMargin insets =
1716 LayoutDeviceMargin(aPresContext->GetSafeAreaInsets()) /
1717 aPresContext->CSSToDevPixelScale();
1718 *aTop = insets.top;
1719 *aRight = insets.right;
1720 *aBottom = insets.bottom;
1721 *aLeft = insets.left;
1722}
1723
1724void Gecko_PrintfStderr(const nsCString* aStr) {
1725 printf_stderr("%s", aStr->get());
1726}
1727
1728nsAtom* Gecko_Element_ImportedPart(const nsAttrValue* aValue,
1729 nsAtom* aPartName) {
1730 if (aValue->Type() != nsAttrValue::eShadowParts) {
1731 return nullptr;
1732 }
1733 return aValue->GetShadowPartsValue().GetReverse(aPartName);
1734}
1735
1736nsAtom** Gecko_Element_ExportedParts(const nsAttrValue* aValue,
1737 nsAtom* aPartName, size_t* aOutLength) {
1738 if (aValue->Type() != nsAttrValue::eShadowParts) {
1739 return nullptr;
1740 }
1741 auto* parts = aValue->GetShadowPartsValue().Get(aPartName);
1742 if (!parts) {
1743 return nullptr;
1744 }
1745 *aOutLength = parts->Length();
1746 static_assert(sizeof(RefPtr<nsAtom>) == sizeof(nsAtom*));
1747 static_assert(alignof(RefPtr<nsAtom>) == alignof(nsAtom*));
1748 return reinterpret_cast<nsAtom**>(parts->Elements());
1749}
1750
1751uint64_t Gecko_Element_GetSubtreeBloomFilter(const Element* aElement) {
1752 return aElement->GetSubtreeBloomFilter();
1753}
1754
1755bool StyleSingleFontFamily::IsNamedFamily(const nsAString& aFamilyName) const {
1756 if (!IsFamilyName()) {
1757 return false;
1758 }
1759 nsDependentAtomString name(AsFamilyName().name.AsAtom());
1760 return name.Equals(aFamilyName, nsCaseInsensitiveStringComparator);
1761}
1762
1763StyleSingleFontFamily StyleSingleFontFamily::Parse(
1764 const nsACString& aFamilyOrGenericName) {
1765 // should only be passed a single font - not entirely correct, a family
1766 // *could* have a comma in it but in practice never does so
1767 // for debug purposes this is fine
1768 NS_ASSERTION(aFamilyOrGenericName.FindChar(',') == -1,do { if (!(aFamilyOrGenericName.FindChar(',') == -1)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Convert method should only be passed a single family name"
, "aFamilyOrGenericName.FindChar(',') == -1", "./../../../layout/style/GeckoBindings.cpp"
, 1769); MOZ_PretendNoReturn(); } } while (0)
1769 "Convert method should only be passed a single family name")do { if (!(aFamilyOrGenericName.FindChar(',') == -1)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Convert method should only be passed a single family name"
, "aFamilyOrGenericName.FindChar(',') == -1", "./../../../layout/style/GeckoBindings.cpp"
, 1769); MOZ_PretendNoReturn(); } } while (0)
;
1770
1771 auto genericType = Servo_GenericFontFamily_Parse(&aFamilyOrGenericName);
1772 if (genericType != StyleGenericFontFamily::None) {
1773 return Generic(genericType);
1774 }
1775 return FamilyName({StyleAtom(NS_Atomize(aFamilyOrGenericName)),
1776 StyleFontFamilyNameSyntax::Identifiers});
1777}
1778
1779void StyleSingleFontFamily::AppendToString(nsACString& aName,
1780 bool aQuote) const {
1781 if (IsFamilyName()) {
1782 const auto& name = AsFamilyName();
1783 if (!aQuote) {
1784 aName.Append(nsAutoAtomCString(name.name.AsAtom()));
1785 return;
1786 }
1787 Servo_FamilyName_Serialize(&name, &aName);
1788 return;
1789 }
1790
1791 switch (AsGeneric()) {
1792 case StyleGenericFontFamily::None:
1793 case StyleGenericFontFamily::MozEmoji:
1794 MOZ_FALLTHROUGH_ASSERT("Should never appear in a font-family name!")do { do { } while (false); MOZ_ReportCrash("" "MOZ_FALLTHROUGH_ASSERT: "
"Should never appear in a font-family name!", "./../../../layout/style/GeckoBindings.cpp"
, 1794); AnnotateMozCrashReason("MOZ_CRASH(" "MOZ_FALLTHROUGH_ASSERT: "
"Should never appear in a font-family name!" ")"); do { MOZ_CrashSequence
(__null, 1794); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
1795 case StyleGenericFontFamily::Serif:
1796 return aName.AppendLiteral("serif");
1797 case StyleGenericFontFamily::SansSerif:
1798 return aName.AppendLiteral("sans-serif");
1799 case StyleGenericFontFamily::Monospace:
1800 return aName.AppendLiteral("monospace");
1801 case StyleGenericFontFamily::Cursive:
1802 return aName.AppendLiteral("cursive");
1803 case StyleGenericFontFamily::Fantasy:
1804 return aName.AppendLiteral("fantasy");
1805 case StyleGenericFontFamily::Math:
1806 return aName.AppendLiteral("math");
1807 case StyleGenericFontFamily::SystemUi:
1808 return aName.AppendLiteral("system-ui");
1809 }
1810 MOZ_ASSERT_UNREACHABLE("Unknown generic font-family!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown generic font-family!" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown generic font-family!" ")"
); do { MOZ_CrashSequence(__null, 1810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1811 return aName.AppendLiteral("serif");
1812}
1813
1814StyleFontFamilyList StyleFontFamilyList::WithNames(
1815 nsTArray<StyleSingleFontFamily>&& aNames) {
1816 StyleFontFamilyList list;
1817 Servo_FontFamilyList_WithNames(&aNames, &list);
1818 return list;
1819}
1820
1821StyleFontFamilyList StyleFontFamilyList::WithOneUnquotedFamily(
1822 const nsACString& aName) {
1823 AutoTArray<StyleSingleFontFamily, 1> names;
1824 names.AppendElement(StyleSingleFontFamily::FamilyName(
1825 {StyleAtom(NS_Atomize(aName)), StyleFontFamilyNameSyntax::Identifiers}));
1826 return WithNames(std::move(names));
1827}
1828
1829static bool AnchorSideUsesCBWM(
1830 const StyleAnchorSideKeyword& aAnchorSideKeyword) {
1831 switch (aAnchorSideKeyword) {
1832 case StyleAnchorSideKeyword::SelfStart:
1833 case StyleAnchorSideKeyword::SelfEnd:
1834 return false;
1835 case StyleAnchorSideKeyword::Inside:
1836 case StyleAnchorSideKeyword::Outside:
1837 case StyleAnchorSideKeyword::Start:
1838 case StyleAnchorSideKeyword::End:
1839 case StyleAnchorSideKeyword::Center:
1840 return true;
1841 // Return value shouldn't matter for these physical keywords.
1842 case StyleAnchorSideKeyword::Left:
1843 case StyleAnchorSideKeyword::Right:
1844 case StyleAnchorSideKeyword::Top:
1845 case StyleAnchorSideKeyword::Bottom:
1846 return true;
1847 }
1848 return false;
1849}
1850
1851bool Gecko_GetAnchorPosOffset(const AnchorPosOffsetResolutionParams* aParams,
1852 const nsAtom* aAnchorName,
1853 const StyleCascadeLevel* aTreeScope,
1854 StylePhysicalSide aPropSide,
1855 StyleAnchorSideKeyword aAnchorSideKeyword,
1856 float aPercentage, Length* aOut) {
1857 if (!aParams || !aParams->mBaseParams.mFrame) {
1858 return false;
1859 }
1860 const auto* positioned = aParams->mBaseParams.mFrame;
1861 const auto* containingBlock = positioned->GetParent();
1862 auto* cache = aParams->mBaseParams.mCache;
1863 const auto info = AnchorPositioningUtils::ResolveAnchorPosRect(
1864 positioned, containingBlock, {aAnchorName, *aTreeScope},
1865 !aParams->mCBSize, cache);
1866 if (!info) {
1867 return false;
1868 }
1869 if (cache) {
1870 // Cache is set during reflow, which is really the only time we want to
1871 // actively modify scroll compensation state & side.
1872 if (info->mCompensatesForScroll) {
1873 const auto axis = [aPropSide]() {
1874 switch (aPropSide) {
1875 case StylePhysicalSide::Left:
1876 case StylePhysicalSide::Right:
1877 return PhysicalAxis::Horizontal;
1878 case StylePhysicalSide::Top:
1879 case StylePhysicalSide::Bottom:
1880 break;
1881 default:
1882 MOZ_ASSERT_UNREACHABLE("Unhandled side?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unhandled side?" ")", "./../../../layout/style/GeckoBindings.cpp"
, 1882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unhandled side?" ")"); do { MOZ_CrashSequence
(__null, 1882); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1883 }
1884 return PhysicalAxis::Vertical;
1885 }();
1886 cache->mReferenceData->AdjustCompensatingForScroll(axis);
1887 // Non scroll-compensated anchor will not have any impact on the
1888 // containing block due to scrolling. See documentation for
1889 // `mScrollCompensatedSides`.
1890 cache->mReferenceData->mScrollCompensatedSides |=
1891 SideToSideBit(ToSide(aPropSide));
1892 }
1893 }
1894 // Compute the offset here in C++, where translating between physical/logical
1895 // coordinates is easier.
1896
1897 const auto usesCBWM = AnchorSideUsesCBWM(aAnchorSideKeyword);
1898 const auto cbwm = containingBlock->GetWritingMode();
1899 const auto wm =
1900 usesCBWM ? cbwm : aParams->mBaseParams.mFrame->GetWritingMode();
1901 const auto [rect, logicalCBSize] = [&] {
1902 // We need `AnchorPosReferenceData` to compute the anchor offset against
1903 // the adjusted CB, so make the best attempt to retrieve it.
1904 // TODO(dshin, bug 2005207): We really need to unify containing block
1905 // lookups and clean up cache lookups here.
1906 const auto* referenceData =
1907 cache ? cache->mReferenceData
1908 : positioned->GetProperty(nsIFrame::AnchorPosReferences());
1909 if (!referenceData) {
1910 return std::make_pair(
1911 info->mRect, aParams->mCBSize ? aParams->mCBSize->ConvertTo(wm, cbwm)
1912 : containingBlock->PaddingSize(wm));
1913 }
1914 // Offset happens from padding rect.
1915 const auto offset = referenceData->mAdjustedContainingBlock.TopLeft() -
1916 referenceData->mOriginalContainingBlockRect.TopLeft();
1917 return std::make_pair(
1918 info->mRect - offset,
1919 aParams->mCBSize
1920 ? aParams->mCBSize->ConvertTo(wm, cbwm)
1921 : LogicalSize{cbwm, referenceData->mAdjustedContainingBlock.Size()}
1922 .ConvertTo(wm, cbwm));
1923 }();
1924 const LogicalRect logicalAnchorRect{wm, rect,
1925 logicalCBSize.GetPhysicalSize(wm)};
1926 const auto logicalPropSide = wm.LogicalSideForPhysicalSide(ToSide(aPropSide));
1927 const auto propAxis = GetAxis(logicalPropSide);
1928 const auto propEdge = GetEdge(logicalPropSide);
1929
1930 const auto anchorEdge = [&]() {
1931 switch (aAnchorSideKeyword) {
1932 case StyleAnchorSideKeyword::Left:
1933 return GetEdge(wm.LogicalSideForPhysicalSide(eSideLeft));
1934 case StyleAnchorSideKeyword::Right:
1935 return GetEdge(wm.LogicalSideForPhysicalSide(eSideRight));
1936 case StyleAnchorSideKeyword::Top:
1937 return GetEdge(wm.LogicalSideForPhysicalSide(eSideTop));
1938 case StyleAnchorSideKeyword::Bottom:
1939 return GetEdge(wm.LogicalSideForPhysicalSide(eSideBottom));
1940 case StyleAnchorSideKeyword::Inside:
1941 return propEdge;
1942 case StyleAnchorSideKeyword::Outside:
1943 return GetOppositeEdge(propEdge);
1944 case StyleAnchorSideKeyword::Start:
1945 case StyleAnchorSideKeyword::SelfStart:
1946 case StyleAnchorSideKeyword::Center:
1947 return LogicalEdge::Start;
1948 case StyleAnchorSideKeyword::End:
1949 case StyleAnchorSideKeyword::SelfEnd:
1950 return LogicalEdge::End;
1951 }
1952 return LogicalEdge::Start;
1953 }();
1954
1955 nscoord result = [&]() {
1956 // Offset to the desired anchor edge, from the containing block's start
1957 // edge.
1958 const auto anchorOffsetFromStartEdge =
1959 anchorEdge == LogicalEdge::Start ? logicalAnchorRect.Start(propAxis, wm)
1960 : logicalAnchorRect.End(propAxis, wm);
1961 if (propEdge == LogicalEdge::Start) {
1962 return anchorOffsetFromStartEdge;
1963 }
1964 // Need the offset from the end edge of the containing block.
1965 const auto anchorOffsetFromEndEdge =
1966 logicalCBSize.Size(propAxis, wm) - anchorOffsetFromStartEdge;
1967 return anchorOffsetFromEndEdge;
1968 }();
1969
1970 // Apply the percentage value, with the percentage basis as the anchor
1971 // element's size in the relevant axis.
1972 if (aPercentage != 0.f) {
1973 const nscoord anchorSize = LogicalSize{wm, rect.Size()}.Size(propAxis, wm);
1974 result += (propEdge == LogicalEdge::End ? -1 : 1) *
1975 ((aPercentage != 1.f)
1976 ? NSToCoordRoundWithClamp(aPercentage *
1977 static_cast<float>(anchorSize))
1978 : anchorSize);
1979 }
1980 *aOut = Length::FromPixels(CSSPixel::FromAppUnits(result));
1981 return true;
1982}
1983
1984bool Gecko_GetAnchorPosSize(const AnchorPosResolutionParams* aParams,
1985 const nsAtom* aAnchorName,
1986 const mozilla::StyleCascadeLevel* aTreeScope,
1987 StylePhysicalAxis aPropAxis,
1988 StyleAnchorSizeKeyword aAnchorSizeKeyword,
1989 Length* aOut) {
1990 if (!aParams || !aParams->mFrame) {
1991 return false;
1992 }
1993 const auto* positioned = aParams->mFrame;
1994 const auto* containingBlock = positioned->GetParent();
1995 const auto size = AnchorPositioningUtils::ResolveAnchorPosSize(
1996 positioned, containingBlock, {aAnchorName, *aTreeScope}, aParams->mCache);
1997 if (!size) {
1998 return false;
1999 }
2000 const auto l = [&]() {
2001 switch (aAnchorSizeKeyword) {
2002 case StyleAnchorSizeKeyword::None:
2003 switch (aPropAxis) {
2004 case StylePhysicalAxis::Horizontal:
2005 return size->Width();
2006 case StylePhysicalAxis::Vertical:
2007 return size->Height();
2008 }
2009 MOZ_ASSERT_UNREACHABLE("Unexpected physical axis.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected physical axis." ")", "./../../../layout/style/GeckoBindings.cpp"
, 2009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected physical axis." ")");
do { MOZ_CrashSequence(__null, 2009); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2010 return size->Width();
2011 case StyleAnchorSizeKeyword::Width:
2012 return size->Width();
2013 case StyleAnchorSizeKeyword::Height:
2014 return size->Height();
2015 case StyleAnchorSizeKeyword::Inline: {
2016 const auto wm = containingBlock->GetWritingMode();
2017 return LogicalSize{wm, *size}.ISize(wm);
2018 }
2019 case StyleAnchorSizeKeyword::Block: {
2020 const auto wm = containingBlock->GetWritingMode();
2021 return LogicalSize{wm, *size}.BSize(wm);
2022 }
2023 case StyleAnchorSizeKeyword::SelfInline: {
2024 const auto wm = positioned->GetWritingMode();
2025 return LogicalSize{wm, *size}.ISize(wm);
2026 }
2027 case StyleAnchorSizeKeyword::SelfBlock: {
2028 const auto wm = positioned->GetWritingMode();
2029 return LogicalSize{wm, *size}.BSize(wm);
2030 }
2031 }
2032 MOZ_ASSERT_UNREACHABLE("Unhandled anchor size keyword.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unhandled anchor size keyword." ")", "./../../../layout/style/GeckoBindings.cpp"
, 2032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unhandled anchor size keyword." ")"
); do { MOZ_CrashSequence(__null, 2032); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2033 return size->Width();
2034 }();
2035 *aOut = Length::FromPixels(CSSPixel::FromAppUnits(l));
2036 return true;
2037}