Bug Summary

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