forked from mirrors/gecko-dev
		
	 323b5be77a
			
		
	
	
		323b5be77a
		
	
	
	
	
		
			
			The only caller wants CSS pixels, no need to go back and forth. This is the last dependency on the pres context, I think, from the style system font code. Differential Revision: https://phabricator.services.mozilla.com/D19147
		
			
				
	
	
		
			2357 lines
		
	
	
	
		
			82 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2357 lines
		
	
	
	
		
			82 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /* FFI functions for Servo to call into Gecko */
 | |
| 
 | |
| #include "mozilla/GeckoBindings.h"
 | |
| 
 | |
| #include "ChildIterator.h"
 | |
| #include "ErrorReporter.h"
 | |
| #include "GeckoProfiler.h"
 | |
| #include "gfxFontFamilyList.h"
 | |
| #include "gfxFontFeatures.h"
 | |
| #include "nsAnimationManager.h"
 | |
| #include "nsAttrValueInlines.h"
 | |
| #include "nsCSSFrameConstructor.h"
 | |
| #include "nsCSSProps.h"
 | |
| #include "nsCSSPseudoElements.h"
 | |
| #include "nsContentUtils.h"
 | |
| #include "nsDOMTokenList.h"
 | |
| #include "nsDeviceContext.h"
 | |
| #include "nsIContentInlines.h"
 | |
| #include "nsICrashReporter.h"
 | |
| #include "mozilla/dom/DocumentInlines.h"
 | |
| #include "nsILoadContext.h"
 | |
| #include "nsIFrame.h"
 | |
| #include "nsIMemoryReporter.h"
 | |
| #include "nsIMozBrowserFrame.h"
 | |
| #include "nsINode.h"
 | |
| #include "nsIPresShell.h"
 | |
| #include "nsIPresShellInlines.h"
 | |
| #include "nsIPrincipal.h"
 | |
| #include "nsIURI.h"
 | |
| #include "nsFontMetrics.h"
 | |
| #include "nsHTMLStyleSheet.h"
 | |
| #include "nsMappedAttributes.h"
 | |
| #include "nsMediaFeatures.h"
 | |
| #include "nsNameSpaceManager.h"
 | |
| #include "nsNetUtil.h"
 | |
| #include "nsProxyRelease.h"
 | |
| #include "nsString.h"
 | |
| #include "nsStyleStruct.h"
 | |
| #include "nsStyleUtil.h"
 | |
| #include "nsTArray.h"
 | |
| #include "nsTransitionManager.h"
 | |
| #include "nsWindowSizes.h"
 | |
| 
 | |
| #include "mozilla/CORSMode.h"
 | |
| #include "mozilla/DeclarationBlock.h"
 | |
| #include "mozilla/EffectCompositor.h"
 | |
| #include "mozilla/EffectSet.h"
 | |
| #include "mozilla/EventStates.h"
 | |
| #include "mozilla/FontPropertyTypes.h"
 | |
| #include "mozilla/Keyframe.h"
 | |
| #include "mozilla/Mutex.h"
 | |
| #include "mozilla/Preferences.h"
 | |
| #include "mozilla/ServoElementSnapshot.h"
 | |
| #include "mozilla/StaticPrefs.h"
 | |
| #include "mozilla/RestyleManager.h"
 | |
| #include "mozilla/SizeOfState.h"
 | |
| #include "mozilla/StyleAnimationValue.h"
 | |
| #include "mozilla/SystemGroup.h"
 | |
| #include "mozilla/ServoBindings.h"
 | |
| #include "mozilla/ServoTraversalStatistics.h"
 | |
| #include "mozilla/Telemetry.h"
 | |
| #include "mozilla/RWLock.h"
 | |
| #include "mozilla/dom/Element.h"
 | |
| #include "mozilla/dom/ElementInlines.h"
 | |
| #include "mozilla/dom/HTMLTableCellElement.h"
 | |
| #include "mozilla/dom/HTMLBodyElement.h"
 | |
| #include "mozilla/dom/HTMLSlotElement.h"
 | |
| #include "mozilla/dom/MediaList.h"
 | |
| #include "mozilla/dom/SVGElement.h"
 | |
| #include "mozilla/LookAndFeel.h"
 | |
| #include "mozilla/URLExtraData.h"
 | |
| #include "mozilla/dom/CSSMozDocumentRule.h"
 | |
| 
 | |
| #if defined(MOZ_MEMORY)
 | |
| #  include "mozmemory.h"
 | |
| #endif
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::css;
 | |
| using namespace mozilla::dom;
 | |
| 
 | |
| #define SERVO_ARC_TYPE(name_, type_)                 \
 | |
|   already_AddRefed<type_> type_##Strong::Consume() { \
 | |
|     RefPtr<type_> result;                            \
 | |
|     result.swap(mPtr);                               \
 | |
|     return result.forget();                          \
 | |
|   }
 | |
| #include "mozilla/ServoArcTypeList.h"
 | |
| SERVO_ARC_TYPE(ComputedStyle, ComputedStyle)
 | |
| #undef SERVO_ARC_TYPE
 | |
| 
 | |
| // Definitions of the global traversal stats.
 | |
| bool ServoTraversalStatistics::sActive = false;
 | |
| ServoTraversalStatistics ServoTraversalStatistics::sSingleton;
 | |
| 
 | |
| static RWLock* sServoFFILock = nullptr;
 | |
| 
 | |
| static const nsFont* ThreadSafeGetDefaultFontHelper(
 | |
|     const nsPresContext* aPresContext, nsAtom* aLanguage, uint8_t aGenericId) {
 | |
|   bool needsCache = false;
 | |
|   const nsFont* retval;
 | |
| 
 | |
|   auto GetDefaultFont = [&](bool* aNeedsToCache) {
 | |
|     auto* prefs =
 | |
|         aPresContext->Document()->GetFontPrefsForLang(aLanguage, aNeedsToCache);
 | |
|     return prefs ? prefs->GetDefaultFont(aGenericId) : nullptr;
 | |
|   };
 | |
| 
 | |
|   {
 | |
|     AutoReadLock guard(*sServoFFILock);
 | |
|     retval = GetDefaultFont(&needsCache);
 | |
|   }
 | |
|   if (!needsCache) {
 | |
|     return retval;
 | |
|   }
 | |
|   {
 | |
|     AutoWriteLock guard(*sServoFFILock);
 | |
|     retval = GetDefaultFont(nullptr);
 | |
|   }
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Does this child count as significant for selector matching?
 | |
|  *
 | |
|  * See nsStyleUtil::IsSignificantChild for details.
 | |
|  */
 | |
| bool Gecko_IsSignificantChild(RawGeckoNodeBorrowed aNode,
 | |
|                               bool aWhitespaceIsSignificant) {
 | |
|   return nsStyleUtil::ThreadSafeIsSignificantChild(aNode->AsContent(),
 | |
|                                                    aWhitespaceIsSignificant);
 | |
| }
 | |
| 
 | |
| RawGeckoNodeBorrowedOrNull Gecko_GetLastChild(RawGeckoNodeBorrowed aNode) {
 | |
|   return aNode->GetLastChild();
 | |
| }
 | |
| 
 | |
| RawGeckoNodeBorrowedOrNull Gecko_GetPreviousSibling(
 | |
|     RawGeckoNodeBorrowed aNode) {
 | |
|   return aNode->GetPreviousSibling();
 | |
| }
 | |
| 
 | |
| RawGeckoNodeBorrowedOrNull Gecko_GetFlattenedTreeParentNode(
 | |
|     RawGeckoNodeBorrowed aNode) {
 | |
|   return aNode->GetFlattenedTreeParentNodeForStyle();
 | |
| }
 | |
| 
 | |
| RawGeckoElementBorrowedOrNull Gecko_GetBeforeOrAfterPseudo(
 | |
|     RawGeckoElementBorrowed aElement, bool aIsBefore) {
 | |
|   MOZ_ASSERT(aElement);
 | |
|   MOZ_ASSERT(aElement->HasProperties());
 | |
| 
 | |
|   return aIsBefore ? nsLayoutUtils::GetBeforePseudo(aElement)
 | |
|                    : nsLayoutUtils::GetAfterPseudo(aElement);
 | |
| }
 | |
| 
 | |
| nsTArray<nsIContent*>* Gecko_GetAnonymousContentForElement(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   nsIAnonymousContentCreator* ac = do_QueryFrame(aElement->GetPrimaryFrame());
 | |
|   if (!ac) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   auto* array = new nsTArray<nsIContent*>();
 | |
|   nsContentUtils::AppendNativeAnonymousChildren(aElement, *array, 0);
 | |
|   return array;
 | |
| }
 | |
| 
 | |
| void Gecko_DestroyAnonymousContentList(nsTArray<nsIContent*>* aAnonContent) {
 | |
|   MOZ_ASSERT(aAnonContent);
 | |
|   delete aAnonContent;
 | |
| }
 | |
| 
 | |
| const nsTArray<RefPtr<nsINode>>* Gecko_GetAssignedNodes(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   MOZ_ASSERT(HTMLSlotElement::FromNode(aElement));
 | |
|   return &static_cast<const HTMLSlotElement*>(aElement)->AssignedNodes();
 | |
| }
 | |
| 
 | |
| void Gecko_ComputedStyle_Init(ComputedStyle* aStyle,
 | |
|                               const ServoComputedData* aValues,
 | |
|                               CSSPseudoElementType aPseudoType,
 | |
|                               nsAtom* aPseudoTag) {
 | |
|   new (KnownNotNull, aStyle) ComputedStyle(aPseudoTag, aPseudoType,
 | |
|                                            ServoComputedDataForgotten(aValues));
 | |
| }
 | |
| 
 | |
| ServoComputedData::ServoComputedData(const ServoComputedDataForgotten aValue) {
 | |
|   PodAssign(this, aValue.mPtr);
 | |
| }
 | |
| 
 | |
| MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoStyleStructsMallocEnclosingSizeOf)
 | |
| 
 | |
| void ServoComputedData::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const {
 | |
|   // Note: GetStyleFoo() returns a pointer to an nsStyleFoo that sits within a
 | |
|   // servo_arc::Arc, i.e. it is preceded by a word-sized refcount. So we need
 | |
|   // to measure it with a function that can handle an interior pointer. We use
 | |
|   // ServoStyleStructsEnclosingMallocSizeOf to clearly identify in DMD's
 | |
|   // output the memory measured here.
 | |
| #define STYLE_STRUCT(name_)                                       \
 | |
|   static_assert(alignof(nsStyle##name_) <= sizeof(size_t),        \
 | |
|                 "alignment will break AddSizeOfExcludingThis()"); \
 | |
|   const void* p##name_ = GetStyle##name_();                       \
 | |
|   if (!aSizes.mState.HaveSeenPtr(p##name_)) {                     \
 | |
|     aSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_) +=             \
 | |
|         ServoStyleStructsMallocEnclosingSizeOf(p##name_);         \
 | |
|   }
 | |
| #include "nsStyleStructList.h"
 | |
| #undef STYLE_STRUCT
 | |
| 
 | |
|   if (visited_style.mPtr && !aSizes.mState.HaveSeenPtr(visited_style.mPtr)) {
 | |
|     visited_style.mPtr->AddSizeOfIncludingThis(
 | |
|         aSizes, &aSizes.mLayoutComputedValuesVisited);
 | |
|   }
 | |
| 
 | |
|   // Measurement of the following members may be added later if DMD finds it is
 | |
|   // worthwhile:
 | |
|   // - custom_properties
 | |
|   // - writing_mode
 | |
|   // - rules
 | |
|   // - font_computation_data
 | |
| }
 | |
| 
 | |
| void Gecko_ComputedStyle_Destroy(ComputedStyle* aStyle) {
 | |
|   aStyle->~ComputedStyle();
 | |
| }
 | |
| 
 | |
| void Gecko_ConstructStyleChildrenIterator(
 | |
|     RawGeckoElementBorrowed aElement,
 | |
|     RawGeckoStyleChildrenIteratorBorrowedMut aIterator) {
 | |
|   MOZ_ASSERT(aElement);
 | |
|   MOZ_ASSERT(aIterator);
 | |
|   new (aIterator) StyleChildrenIterator(aElement);
 | |
| }
 | |
| 
 | |
| void Gecko_DestroyStyleChildrenIterator(
 | |
|     RawGeckoStyleChildrenIteratorBorrowedMut aIterator) {
 | |
|   MOZ_ASSERT(aIterator);
 | |
| 
 | |
|   aIterator->~StyleChildrenIterator();
 | |
| }
 | |
| 
 | |
| RawGeckoNodeBorrowed Gecko_GetNextStyleChild(
 | |
|     RawGeckoStyleChildrenIteratorBorrowedMut aIterator) {
 | |
|   MOZ_ASSERT(aIterator);
 | |
|   return aIterator->GetNextChild();
 | |
| }
 | |
| 
 | |
| bool Gecko_VisitedStylesEnabled(const Document* aDoc) {
 | |
|   MOZ_ASSERT(aDoc);
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   if (!StaticPrefs::layout_css_visited_links_enabled()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   if (aDoc->IsBeingUsedAsImage()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   nsILoadContext* loadContext = aDoc->GetLoadContext();
 | |
|   if (loadContext && loadContext->UsePrivateBrowsing()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| EventStates::ServoType Gecko_ElementState(RawGeckoElementBorrowed aElement) {
 | |
|   return aElement->StyleState().ServoValue();
 | |
| }
 | |
| 
 | |
| bool Gecko_IsRootElement(RawGeckoElementBorrowed aElement) {
 | |
|   return aElement->OwnerDoc()->GetRootElement() == aElement;
 | |
| }
 | |
| 
 | |
| // Dirtiness tracking.
 | |
| void Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags) {
 | |
|   const_cast<nsINode*>(aNode)->SetFlags(aFlags);
 | |
| }
 | |
| 
 | |
| void Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags) {
 | |
|   const_cast<nsINode*>(aNode)->UnsetFlags(aFlags);
 | |
| }
 | |
| 
 | |
| void Gecko_NoteDirtyElement(RawGeckoElementBorrowed aElement) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   const_cast<Element*>(aElement)->NoteDirtyForServo();
 | |
| }
 | |
| 
 | |
| void Gecko_NoteDirtySubtreeForInvalidation(RawGeckoElementBorrowed aElement) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   const_cast<Element*>(aElement)->NoteDirtySubtreeForServo();
 | |
| }
 | |
| 
 | |
| void Gecko_NoteAnimationOnlyDirtyElement(RawGeckoElementBorrowed aElement) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   const_cast<Element*>(aElement)->NoteAnimationOnlyDirtyForServo();
 | |
| }
 | |
| 
 | |
| bool Gecko_AnimationNameMayBeReferencedFromStyle(
 | |
|     RawGeckoPresContextBorrowed aPresContext, nsAtom* aName) {
 | |
|   MOZ_ASSERT(aPresContext);
 | |
|   return aPresContext->AnimationManager()->AnimationMayBeReferenced(aName);
 | |
| }
 | |
| 
 | |
| CSSPseudoElementType Gecko_GetImplementedPseudo(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   return aElement->GetPseudoElementType();
 | |
| }
 | |
| 
 | |
| uint32_t Gecko_CalcStyleDifference(ComputedStyleBorrowed aOldStyle,
 | |
|                                    ComputedStyleBorrowed aNewStyle,
 | |
|                                    bool* aAnyStyleStructChanged,
 | |
|                                    bool* aOnlyResetStructsChanged) {
 | |
|   MOZ_ASSERT(aOldStyle);
 | |
|   MOZ_ASSERT(aNewStyle);
 | |
| 
 | |
|   uint32_t equalStructs;
 | |
|   nsChangeHint result =
 | |
|       aOldStyle->CalcStyleDifference(*aNewStyle, &equalStructs);
 | |
| 
 | |
|   *aAnyStyleStructChanged =
 | |
|       equalStructs != StyleStructConstants::kAllStructsMask;
 | |
| 
 | |
|   const auto kInheritedStructsMask =
 | |
|       StyleStructConstants::kInheritedStructsMask;
 | |
|   *aOnlyResetStructsChanged =
 | |
|       (equalStructs & kInheritedStructsMask) == kInheritedStructsMask;
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| const ServoElementSnapshot* Gecko_GetElementSnapshot(
 | |
|     const ServoElementSnapshotTable* aTable, const Element* aElement) {
 | |
|   MOZ_ASSERT(aTable);
 | |
|   MOZ_ASSERT(aElement);
 | |
| 
 | |
|   return aTable->Get(const_cast<Element*>(aElement));
 | |
| }
 | |
| 
 | |
| bool Gecko_HaveSeenPtr(SeenPtrs* aTable, const void* aPtr) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(aTable);
 | |
|   // Empty Rust allocations are indicated by small values up to the alignment
 | |
|   // of the relevant type. We shouldn't see anything like that here.
 | |
|   MOZ_ASSERT(uintptr_t(aPtr) > 16);
 | |
| 
 | |
|   return aTable->HaveSeenPtr(aPtr);
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull Gecko_GetStyleAttrDeclarationBlock(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
 | |
|   if (!decl) {
 | |
|     return nullptr;
 | |
|   }
 | |
|   return decl->RefRawStrong();
 | |
| }
 | |
| 
 | |
| void Gecko_UnsetDirtyStyleAttr(RawGeckoElementBorrowed aElement) {
 | |
|   DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
 | |
|   if (!decl) {
 | |
|     return;
 | |
|   }
 | |
|   decl->UnsetDirty();
 | |
| }
 | |
| 
 | |
| static const RawServoDeclarationBlockStrong* AsRefRawStrong(
 | |
|     const RefPtr<RawServoDeclarationBlock>& aDecl) {
 | |
|   static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
 | |
|                     sizeof(RawServoDeclarationBlockStrong),
 | |
|                 "RefPtr should just be a pointer");
 | |
|   return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&aDecl);
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull
 | |
| Gecko_GetHTMLPresentationAttrDeclarationBlock(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   const nsMappedAttributes* attrs = aElement->GetMappedAttributes();
 | |
|   if (!attrs) {
 | |
|     auto* svg = SVGElement::FromNodeOrNull(aElement);
 | |
|     if (svg) {
 | |
|       if (auto decl = svg->GetContentDeclarationBlock()) {
 | |
|         return decl->RefRawStrong();
 | |
|       }
 | |
|     }
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return AsRefRawStrong(attrs->GetServoStyle());
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull
 | |
| Gecko_GetExtraContentStyleDeclarations(RawGeckoElementBorrowed aElement) {
 | |
|   if (!aElement->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
 | |
|     return nullptr;
 | |
|   }
 | |
|   const HTMLTableCellElement* cell =
 | |
|       static_cast<const HTMLTableCellElement*>(aElement);
 | |
|   if (nsMappedAttributes* attrs =
 | |
|           cell->GetMappedAttributesInheritedFromTable()) {
 | |
|     return AsRefRawStrong(attrs->GetServoStyle());
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull
 | |
| Gecko_GetUnvisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement) {
 | |
|   nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
 | |
|   if (!sheet) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return AsRefRawStrong(sheet->GetServoUnvisitedLinkDecl());
 | |
| }
 | |
| 
 | |
| StyleSheet* Gecko_StyleSheet_Clone(const StyleSheet* aSheet,
 | |
|                                    const StyleSheet* aNewParentSheet) {
 | |
|   MOZ_ASSERT(aSheet);
 | |
|   MOZ_ASSERT(aSheet->GetParentSheet(), "Should only be used for @import");
 | |
|   MOZ_ASSERT(aNewParentSheet, "Wat");
 | |
| 
 | |
|   RefPtr<StyleSheet> newSheet =
 | |
|       aSheet->Clone(nullptr, nullptr, nullptr, nullptr);
 | |
| 
 | |
|   // NOTE(emilio): This code runs in the StylesheetInner constructor, which
 | |
|   // means that the inner pointer of `aNewParentSheet` still points to the old
 | |
|   // one.
 | |
|   //
 | |
|   // So we _don't_ update neither the parent pointer of the stylesheet, nor the
 | |
|   // child list (yet). This is fixed up in that same constructor.
 | |
|   return static_cast<StyleSheet*>(newSheet.forget().take());
 | |
| }
 | |
| 
 | |
| void Gecko_StyleSheet_AddRef(const StyleSheet* aSheet) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   const_cast<StyleSheet*>(aSheet)->AddRef();
 | |
| }
 | |
| 
 | |
| void Gecko_StyleSheet_Release(const StyleSheet* aSheet) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   const_cast<StyleSheet*>(aSheet)->Release();
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull
 | |
| Gecko_GetVisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement) {
 | |
|   nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
 | |
|   if (!sheet) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return AsRefRawStrong(sheet->GetServoVisitedLinkDecl());
 | |
| }
 | |
| 
 | |
| RawServoDeclarationBlockStrongBorrowedOrNull
 | |
| Gecko_GetActiveLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement) {
 | |
|   nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
 | |
|   if (!sheet) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return AsRefRawStrong(sheet->GetServoActiveLinkDecl());
 | |
| }
 | |
| 
 | |
| static CSSPseudoElementType GetPseudoTypeFromElementForAnimation(
 | |
|     const Element*& aElementOrPseudo) {
 | |
|   if (aElementOrPseudo->IsGeneratedContentContainerForBefore()) {
 | |
|     aElementOrPseudo = aElementOrPseudo->GetParent()->AsElement();
 | |
|     return CSSPseudoElementType::before;
 | |
|   }
 | |
| 
 | |
|   if (aElementOrPseudo->IsGeneratedContentContainerForAfter()) {
 | |
|     aElementOrPseudo = aElementOrPseudo->GetParent()->AsElement();
 | |
|     return CSSPseudoElementType::after;
 | |
|   }
 | |
| 
 | |
|   return CSSPseudoElementType::NotPseudo;
 | |
| }
 | |
| 
 | |
| bool Gecko_GetAnimationRule(
 | |
|     RawGeckoElementBorrowed aElement,
 | |
|     EffectCompositor::CascadeLevel aCascadeLevel,
 | |
|     RawServoAnimationValueMapBorrowedMut aAnimationValues) {
 | |
|   MOZ_ASSERT(aElement);
 | |
| 
 | |
|   Document* doc = aElement->GetComposedDoc();
 | |
|   if (!doc) {
 | |
|     return false;
 | |
|   }
 | |
|   nsPresContext* presContext = doc->GetPresContext();
 | |
|   if (!presContext || !presContext->IsDynamic()) {
 | |
|     // For print or print preview, ignore animations.
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
| 
 | |
|   return presContext->EffectCompositor()->GetServoAnimationRule(
 | |
|       aElement, pseudoType, aCascadeLevel, aAnimationValues);
 | |
| }
 | |
| 
 | |
| bool Gecko_StyleAnimationsEquals(RawGeckoStyleAnimationListBorrowed aA,
 | |
|                                  RawGeckoStyleAnimationListBorrowed aB) {
 | |
|   return *aA == *aB;
 | |
| }
 | |
| 
 | |
| void Gecko_CopyAnimationNames(RawGeckoStyleAnimationListBorrowedMut aDest,
 | |
|                               RawGeckoStyleAnimationListBorrowed aSrc) {
 | |
|   size_t srcLength = aSrc->Length();
 | |
|   aDest->EnsureLengthAtLeast(srcLength);
 | |
| 
 | |
|   for (size_t index = 0; index < srcLength; index++) {
 | |
|     (*aDest)[index].SetName((*aSrc)[index].GetName());
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_SetAnimationName(StyleAnimation* aStyleAnimation, nsAtom* aAtom) {
 | |
|   MOZ_ASSERT(aStyleAnimation);
 | |
| 
 | |
|   aStyleAnimation->SetName(already_AddRefed<nsAtom>(aAtom));
 | |
| }
 | |
| 
 | |
| void Gecko_UpdateAnimations(RawGeckoElementBorrowed aElement,
 | |
|                             ComputedStyleBorrowedOrNull aOldComputedData,
 | |
|                             ComputedStyleBorrowedOrNull aComputedData,
 | |
|                             UpdateAnimationsTasks aTasks) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(aElement);
 | |
| 
 | |
|   if (!aElement->IsInComposedDoc()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsPresContext* presContext = nsContentUtils::GetContextForContent(aElement);
 | |
|   if (!presContext || !presContext->IsDynamic()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
 | |
| 
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
| 
 | |
|   if (aTasks & UpdateAnimationsTasks::CSSAnimations) {
 | |
|     presContext->AnimationManager()->UpdateAnimations(
 | |
|         const_cast<dom::Element*>(aElement), pseudoType, aComputedData);
 | |
|   }
 | |
| 
 | |
|   // aComputedData might be nullptr if the target element is now in a
 | |
|   // display:none subtree. We still call Gecko_UpdateAnimations in this case
 | |
|   // because we need to stop CSS animations in the display:none subtree.
 | |
|   // However, we don't need to update transitions since they are stopped by
 | |
|   // RestyleManager::AnimationsWithDestroyedFrame so we just return early
 | |
|   // here.
 | |
|   if (!aComputedData) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (aTasks & UpdateAnimationsTasks::CSSTransitions) {
 | |
|     MOZ_ASSERT(aOldComputedData);
 | |
|     presContext->TransitionManager()->UpdateTransitions(
 | |
|         const_cast<dom::Element*>(aElement), pseudoType, *aOldComputedData,
 | |
|         *aComputedData);
 | |
|   }
 | |
| 
 | |
|   if (aTasks & UpdateAnimationsTasks::EffectProperties) {
 | |
|     presContext->EffectCompositor()->UpdateEffectProperties(
 | |
|         aComputedData, const_cast<dom::Element*>(aElement), pseudoType);
 | |
|   }
 | |
| 
 | |
|   if (aTasks & UpdateAnimationsTasks::CascadeResults) {
 | |
|     EffectSet* effectSet = EffectSet::GetEffectSet(aElement, pseudoType);
 | |
|     // CSS animations/transitions might have been destroyed as part of the above
 | |
|     // steps so before updating cascade results, we check if there are still any
 | |
|     // animations to update.
 | |
|     if (effectSet) {
 | |
|       // We call UpdateCascadeResults directly (intead of
 | |
|       // MaybeUpdateCascadeResults) since we know for sure that the cascade has
 | |
|       // changed, but we were unable to call MarkCascadeUpdated when we noticed
 | |
|       // it since we avoid mutating state as part of the Servo parallel
 | |
|       // traversal.
 | |
|       presContext->EffectCompositor()->UpdateCascadeResults(
 | |
|           *effectSet, const_cast<Element*>(aElement), pseudoType);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (aTasks & UpdateAnimationsTasks::DisplayChangedFromNone) {
 | |
|     presContext->EffectCompositor()->RequestRestyle(
 | |
|         const_cast<Element*>(aElement), pseudoType,
 | |
|         EffectCompositor::RestyleType::Standard,
 | |
|         EffectCompositor::CascadeLevel::Animations);
 | |
|   }
 | |
| }
 | |
| 
 | |
| size_t Gecko_GetAnimationEffectCount(RawGeckoElementBorrowed aElementOrPseudo) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElementOrPseudo);
 | |
| 
 | |
|   EffectSet* effectSet = EffectSet::GetEffectSet(aElementOrPseudo, pseudoType);
 | |
|   return effectSet ? effectSet->Count() : 0;
 | |
| }
 | |
| 
 | |
| bool Gecko_ElementHasAnimations(RawGeckoElementBorrowed aElement) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
| 
 | |
|   return !!EffectSet::GetEffectSet(aElement, pseudoType);
 | |
| }
 | |
| 
 | |
| bool Gecko_ElementHasCSSAnimations(RawGeckoElementBorrowed aElement) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
|   nsAnimationManager::CSSAnimationCollection* collection =
 | |
|       nsAnimationManager::CSSAnimationCollection ::GetAnimationCollection(
 | |
|           aElement, pseudoType);
 | |
| 
 | |
|   return collection && !collection->mAnimations.IsEmpty();
 | |
| }
 | |
| 
 | |
| bool Gecko_ElementHasCSSTransitions(RawGeckoElementBorrowed aElement) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
|   nsTransitionManager::CSSTransitionCollection* collection =
 | |
|       nsTransitionManager::CSSTransitionCollection ::GetAnimationCollection(
 | |
|           aElement, pseudoType);
 | |
| 
 | |
|   return collection && !collection->mAnimations.IsEmpty();
 | |
| }
 | |
| 
 | |
| size_t Gecko_ElementTransitions_Length(RawGeckoElementBorrowed aElement) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
|   nsTransitionManager::CSSTransitionCollection* collection =
 | |
|       nsTransitionManager::CSSTransitionCollection ::GetAnimationCollection(
 | |
|           aElement, pseudoType);
 | |
| 
 | |
|   return collection ? collection->mAnimations.Length() : 0;
 | |
| }
 | |
| 
 | |
| static CSSTransition* GetCurrentTransitionAt(RawGeckoElementBorrowed aElement,
 | |
|                                              size_t aIndex) {
 | |
|   CSSPseudoElementType pseudoType =
 | |
|       GetPseudoTypeFromElementForAnimation(aElement);
 | |
|   nsTransitionManager::CSSTransitionCollection* collection =
 | |
|       nsTransitionManager::CSSTransitionCollection ::GetAnimationCollection(
 | |
|           aElement, pseudoType);
 | |
|   if (!collection) {
 | |
|     return nullptr;
 | |
|   }
 | |
|   nsTArray<RefPtr<CSSTransition>>& transitions = collection->mAnimations;
 | |
|   return aIndex < transitions.Length() ? transitions[aIndex].get() : nullptr;
 | |
| }
 | |
| 
 | |
| nsCSSPropertyID Gecko_ElementTransitions_PropertyAt(
 | |
|     RawGeckoElementBorrowed aElement, size_t aIndex) {
 | |
|   CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
 | |
|   return transition ? transition->TransitionProperty()
 | |
|                     : nsCSSPropertyID::eCSSProperty_UNKNOWN;
 | |
| }
 | |
| 
 | |
| RawServoAnimationValueBorrowedOrNull Gecko_ElementTransitions_EndValueAt(
 | |
|     RawGeckoElementBorrowed aElement, size_t aIndex) {
 | |
|   CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
 | |
|   return transition ? transition->ToValue().mServo.get() : nullptr;
 | |
| }
 | |
| 
 | |
| double Gecko_GetProgressFromComputedTiming(
 | |
|     RawGeckoComputedTimingBorrowed aComputedTiming) {
 | |
|   return aComputedTiming->mProgress.Value();
 | |
| }
 | |
| 
 | |
| double Gecko_GetPositionInSegment(
 | |
|     RawGeckoAnimationPropertySegmentBorrowed aSegment, double aProgress,
 | |
|     ComputedTimingFunction::BeforeFlag aBeforeFlag) {
 | |
|   MOZ_ASSERT(aSegment->mFromKey < aSegment->mToKey,
 | |
|              "The segment from key should be less than to key");
 | |
| 
 | |
|   double positionInSegment = (aProgress - aSegment->mFromKey) /
 | |
|                              // To avoid floating precision inaccuracies, make
 | |
|                              // sure we calculate both the numerator and
 | |
|                              // denominator using double precision.
 | |
|                              (double(aSegment->mToKey) - aSegment->mFromKey);
 | |
| 
 | |
|   return ComputedTimingFunction::GetPortion(aSegment->mTimingFunction,
 | |
|                                             positionInSegment, aBeforeFlag);
 | |
| }
 | |
| 
 | |
| RawServoAnimationValueBorrowedOrNull Gecko_AnimationGetBaseStyle(
 | |
|     void* aBaseStyles, nsCSSPropertyID aProperty) {
 | |
|   auto base =
 | |
|       static_cast<nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue>*>(
 | |
|           aBaseStyles);
 | |
|   return base->GetWeak(aProperty);
 | |
| }
 | |
| 
 | |
| void Gecko_FillAllImageLayers(nsStyleImageLayers* aLayers, uint32_t aMaxLen) {
 | |
|   aLayers->FillAllLayers(aMaxLen);
 | |
| }
 | |
| 
 | |
| bool Gecko_IsDocumentBody(RawGeckoElementBorrowed aElement) {
 | |
|   Document* doc = aElement->GetUncomposedDoc();
 | |
|   return doc && doc->GetBodyElement() == aElement;
 | |
| }
 | |
| 
 | |
| nscolor Gecko_GetLookAndFeelSystemColor(
 | |
|     int32_t aId, RawGeckoPresContextBorrowed aPresContext) {
 | |
|   bool useStandinsForNativeColors = aPresContext && !aPresContext->IsChrome();
 | |
|   nscolor result;
 | |
|   LookAndFeel::ColorID colorId = static_cast<LookAndFeel::ColorID>(aId);
 | |
|   AutoWriteLock guard(*sServoFFILock);
 | |
|   LookAndFeel::GetColor(colorId, useStandinsForNativeColors, &result);
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| bool Gecko_MatchLang(RawGeckoElementBorrowed aElement, nsAtom* aOverrideLang,
 | |
|                      bool aHasOverrideLang, const char16_t* aValue) {
 | |
|   MOZ_ASSERT(!(aOverrideLang && !aHasOverrideLang),
 | |
|              "aHasOverrideLang should only be set when aOverrideLang is null");
 | |
|   MOZ_ASSERT(aValue, "null lang parameter");
 | |
|   if (!aValue || !*aValue) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // We have to determine the language of the current element.  Since
 | |
|   // this is currently no property and since the language is inherited
 | |
|   // from the parent we have to be prepared to look at all parent
 | |
|   // nodes.  The language itself is encoded in the LANG attribute.
 | |
|   if (auto* language = aHasOverrideLang ? aOverrideLang : aElement->GetLang()) {
 | |
|     return nsStyleUtil::DashMatchCompare(
 | |
|         nsDependentAtomString(language), nsDependentString(aValue),
 | |
|         nsASCIICaseInsensitiveStringComparator());
 | |
|   }
 | |
| 
 | |
|   // Try to get the language from the HTTP header or if this
 | |
|   // is missing as well from the preferences.
 | |
|   // The content language can be a comma-separated list of
 | |
|   // language codes.
 | |
|   nsAutoString language;
 | |
|   aElement->OwnerDoc()->GetContentLanguage(language);
 | |
| 
 | |
|   nsDependentString langString(aValue);
 | |
|   language.StripWhitespace();
 | |
|   for (auto const& lang : language.Split(char16_t(','))) {
 | |
|     if (nsStyleUtil::DashMatchCompare(
 | |
|             lang, langString, nsASCIICaseInsensitiveStringComparator())) {
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| nsAtom* Gecko_GetXMLLangValue(RawGeckoElementBorrowed aElement) {
 | |
|   const nsAttrValue* attr =
 | |
|       aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
 | |
| 
 | |
|   if (!attr) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom);
 | |
| 
 | |
|   RefPtr<nsAtom> atom = attr->GetAtomValue();
 | |
|   return atom.forget().take();
 | |
| }
 | |
| 
 | |
| Document::DocumentTheme Gecko_GetDocumentLWTheme(const Document* aDocument) {
 | |
|   return aDocument->ThreadSafeGetDocumentLWTheme();
 | |
| }
 | |
| 
 | |
| bool Gecko_IsTableBorderNonzero(RawGeckoElementBorrowed aElement) {
 | |
|   if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
 | |
|     return false;
 | |
|   }
 | |
|   const nsAttrValue* val = aElement->GetParsedAttr(nsGkAtoms::border);
 | |
|   return val &&
 | |
|          (val->Type() != nsAttrValue::eInteger || val->GetIntegerValue() != 0);
 | |
| }
 | |
| 
 | |
| bool Gecko_IsBrowserFrame(RawGeckoElementBorrowed aElement) {
 | |
|   nsIMozBrowserFrame* browserFrame =
 | |
|       const_cast<Element*>(aElement)->GetAsMozBrowserFrame();
 | |
|   return browserFrame && browserFrame->GetReallyIsBrowser();
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static nsAtom* LangValue(Implementor* aElement) {
 | |
|   // TODO(emilio): Deduplicate a bit with nsIContent::GetLang().
 | |
|   const nsAttrValue* attr =
 | |
|       aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
 | |
|   if (!attr && aElement->SupportsLangAttr()) {
 | |
|     attr = aElement->GetParsedAttr(nsGkAtoms::lang);
 | |
|   }
 | |
| 
 | |
|   if (!attr) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom);
 | |
|   RefPtr<nsAtom> atom = attr->GetAtomValue();
 | |
|   return atom.forget().take();
 | |
| }
 | |
| 
 | |
| template <typename Implementor, typename MatchFn>
 | |
| static bool DoMatch(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                     MatchFn aMatch) {
 | |
|   if (MOZ_LIKELY(aNS)) {
 | |
|     int32_t ns = aNS == nsGkAtoms::_empty
 | |
|                      ? kNameSpaceID_None
 | |
|                      : nsContentUtils::NameSpaceManager()->GetNameSpaceID(
 | |
|                            aNS, aElement->IsInChromeDocument());
 | |
| 
 | |
|     MOZ_ASSERT(ns == nsContentUtils::NameSpaceManager()->GetNameSpaceID(
 | |
|                          aNS, aElement->IsInChromeDocument()));
 | |
|     NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
 | |
|     const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
 | |
|     return value && aMatch(value);
 | |
|   }
 | |
| 
 | |
|   // No namespace means any namespace - we have to check them all. :-(
 | |
|   BorrowedAttrInfo attrInfo;
 | |
|   for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
 | |
|     if (attrInfo.mName->LocalName() != aName) {
 | |
|       continue;
 | |
|     }
 | |
|     if (aMatch(attrInfo.mValue)) {
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool HasAttr(Implementor* aElement, nsAtom* aNS, nsAtom* aName) {
 | |
|   auto match = [](const nsAttrValue* aValue) { return true; };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrEquals(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                        nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| #define WITH_COMPARATOR(ignore_case_, c_, expr_) \
 | |
|   if (ignore_case_) {                            \
 | |
|     const nsCaseInsensitiveStringComparator c_;  \
 | |
|     return expr_;                                \
 | |
|   } else {                                       \
 | |
|     const nsDefaultStringComparator c_;          \
 | |
|     return expr_;                                \
 | |
|   }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrDashEquals(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                            nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     nsAutoString str;
 | |
|     aValue->ToString(str);
 | |
|     WITH_COMPARATOR(
 | |
|         aIgnoreCase, c,
 | |
|         nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c))
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrIncludes(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                          nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     nsAutoString str;
 | |
|     aValue->ToString(str);
 | |
|     WITH_COMPARATOR(
 | |
|         aIgnoreCase, c,
 | |
|         nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c))
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrHasSubstring(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                              nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     nsAutoString str;
 | |
|     aValue->ToString(str);
 | |
|     WITH_COMPARATOR(aIgnoreCase, c,
 | |
|                     FindInReadable(nsDependentAtomString(aStr), str, c))
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrHasPrefix(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                           nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     nsAutoString str;
 | |
|     aValue->ToString(str);
 | |
|     WITH_COMPARATOR(aIgnoreCase, c,
 | |
|                     StringBeginsWith(str, nsDependentAtomString(aStr), c))
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| template <typename Implementor>
 | |
| static bool AttrHasSuffix(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
 | |
|                           nsAtom* aStr, bool aIgnoreCase) {
 | |
|   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
 | |
|     nsAutoString str;
 | |
|     aValue->ToString(str);
 | |
|     WITH_COMPARATOR(aIgnoreCase, c,
 | |
|                     StringEndsWith(str, nsDependentAtomString(aStr), c))
 | |
|   };
 | |
|   return DoMatch(aElement, aNS, aName, match);
 | |
| }
 | |
| 
 | |
| #define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_)      \
 | |
|   nsAtom* prefix_##LangValue(implementor_ aElement) {                          \
 | |
|     return LangValue(aElement);                                                \
 | |
|   }                                                                            \
 | |
|   bool prefix_##HasAttr(implementor_ aElement, nsAtom* aNS, nsAtom* aName) {   \
 | |
|     return HasAttr(aElement, aNS, aName);                                      \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrEquals(implementor_ aElement, nsAtom* aNS, nsAtom* aName,  \
 | |
|                            nsAtom* aStr, bool aIgnoreCase) {                   \
 | |
|     return AttrEquals(aElement, aNS, aName, aStr, aIgnoreCase);                \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrDashEquals(implementor_ aElement, nsAtom* aNS,             \
 | |
|                                nsAtom* aName, nsAtom* aStr,                    \
 | |
|                                bool aIgnoreCase) {                             \
 | |
|     return AttrDashEquals(aElement, aNS, aName, aStr, aIgnoreCase);            \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrIncludes(implementor_ aElement, nsAtom* aNS,               \
 | |
|                              nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) {  \
 | |
|     return AttrIncludes(aElement, aNS, aName, aStr, aIgnoreCase);              \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrHasSubstring(implementor_ aElement, nsAtom* aNS,           \
 | |
|                                  nsAtom* aName, nsAtom* aStr,                  \
 | |
|                                  bool aIgnoreCase) {                           \
 | |
|     return AttrHasSubstring(aElement, aNS, aName, aStr, aIgnoreCase);          \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrHasPrefix(implementor_ aElement, nsAtom* aNS,              \
 | |
|                               nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) { \
 | |
|     return AttrHasPrefix(aElement, aNS, aName, aStr, aIgnoreCase);             \
 | |
|   }                                                                            \
 | |
|   bool prefix_##AttrHasSuffix(implementor_ aElement, nsAtom* aNS,              \
 | |
|                               nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) { \
 | |
|     return AttrHasSuffix(aElement, aNS, aName, aStr, aIgnoreCase);             \
 | |
|   }
 | |
| 
 | |
| SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
 | |
| SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
 | |
|                                            const ServoElementSnapshot*)
 | |
| 
 | |
| #undef SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS
 | |
| 
 | |
| nsAtom* Gecko_Atomize(const char* aString, uint32_t aLength) {
 | |
|   return NS_Atomize(nsDependentCSubstring(aString, aLength)).take();
 | |
| }
 | |
| 
 | |
| nsAtom* Gecko_Atomize16(const nsAString* aString) {
 | |
|   return NS_Atomize(*aString).take();
 | |
| }
 | |
| 
 | |
| void Gecko_AddRefAtom(nsAtom* aAtom) { NS_ADDREF(aAtom); }
 | |
| 
 | |
| void Gecko_ReleaseAtom(nsAtom* aAtom) { NS_RELEASE(aAtom); }
 | |
| 
 | |
| void Gecko_nsTArray_FontFamilyName_AppendNamed(nsTArray<FontFamilyName>* aNames,
 | |
|                                                nsAtom* aName, bool aQuoted) {
 | |
|   aNames->AppendElement(
 | |
|       FontFamilyName(aName, aQuoted ? eQuotedName : eUnquotedName));
 | |
| }
 | |
| 
 | |
| void Gecko_nsTArray_FontFamilyName_AppendGeneric(
 | |
|     nsTArray<FontFamilyName>* aNames, FontFamilyType aType) {
 | |
|   aNames->AppendElement(FontFamilyName(aType));
 | |
| }
 | |
| 
 | |
| SharedFontList* Gecko_SharedFontList_Create() {
 | |
|   RefPtr<SharedFontList> fontlist = new SharedFontList();
 | |
|   return fontlist.forget().take();
 | |
| }
 | |
| 
 | |
| MOZ_DEFINE_MALLOC_SIZE_OF(GeckoSharedFontListMallocSizeOf)
 | |
| 
 | |
| size_t Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(
 | |
|     SharedFontList* aFontlist) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   return aFontlist->SizeOfIncludingThisIfUnshared(
 | |
|       GeckoSharedFontListMallocSizeOf);
 | |
| }
 | |
| 
 | |
| size_t Gecko_SharedFontList_SizeOfIncludingThis(SharedFontList* aFontlist) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   return aFontlist->SizeOfIncludingThis(GeckoSharedFontListMallocSizeOf);
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(mozilla::SharedFontList, SharedFontList);
 | |
| 
 | |
| void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src) {
 | |
|   dst->fontlist = src->fontlist;
 | |
| }
 | |
| 
 | |
| void Gecko_nsFont_InitSystem(nsFont* aDest, int32_t aFontId,
 | |
|                              const nsStyleFont* aFont,
 | |
|                              RawGeckoPresContextBorrowed aPresContext) {
 | |
|   const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper(
 | |
|       aPresContext, aFont->mLanguage, kPresContext_DefaultVariableFont_ID);
 | |
| 
 | |
|   // We have passed uninitialized memory to this function,
 | |
|   // initialize it. We can't simply return an nsFont because then
 | |
|   // we need to know its size beforehand. Servo cannot initialize nsFont
 | |
|   // itself, so this will do.
 | |
|   nsFont* system = new (aDest) nsFont(*defaultVariableFont);
 | |
| 
 | |
|   MOZ_RELEASE_ASSERT(system);
 | |
| 
 | |
|   *aDest = *defaultVariableFont;
 | |
|   LookAndFeel::FontID fontID = static_cast<LookAndFeel::FontID>(aFontId);
 | |
| 
 | |
|   AutoWriteLock guard(*sServoFFILock);
 | |
|   nsLayoutUtils::ComputeSystemFont(aDest, fontID, defaultVariableFont);
 | |
| }
 | |
| 
 | |
| void Gecko_nsFont_Destroy(nsFont* aDest) { aDest->~nsFont(); }
 | |
| 
 | |
| gfxFontFeatureValueSet* Gecko_ConstructFontFeatureValueSet() {
 | |
|   return new gfxFontFeatureValueSet();
 | |
| }
 | |
| 
 | |
| nsTArray<unsigned int>* Gecko_AppendFeatureValueHashEntry(
 | |
|     gfxFontFeatureValueSet* aFontFeatureValues, nsAtom* aFamily,
 | |
|     uint32_t aAlternate, nsAtom* aName) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   static_assert(sizeof(unsigned int) == sizeof(uint32_t),
 | |
|                 "sizeof unsigned int and uint32_t must be the same");
 | |
|   return aFontFeatureValues->AppendFeatureValueHashEntry(
 | |
|       nsAtomCString(aFamily), nsDependentAtomString(aName), aAlternate);
 | |
| }
 | |
| 
 | |
| void Gecko_nsFont_SetFontFeatureValuesLookup(
 | |
|     nsFont* aFont, const RawGeckoPresContext* aPresContext) {
 | |
|   aFont->featureValueLookup = aPresContext->GetFontFeatureValuesLookup();
 | |
| }
 | |
| 
 | |
| float Gecko_FontStretch_ToFloat(mozilla::FontStretch aStretch) {
 | |
|   // Servo represents percentages with 1. being 100%.
 | |
|   return aStretch.Percentage() / 100.0f;
 | |
| }
 | |
| 
 | |
| void Gecko_FontStretch_SetFloat(mozilla::FontStretch* aStretch, float aFloat) {
 | |
|   // Servo represents percentages with 1. being 100%.
 | |
|   //
 | |
|   // Also, the font code assumes a given maximum that style doesn't really need
 | |
|   // to know about. So clamp here at the boundary.
 | |
|   *aStretch = FontStretch(std::min(aFloat * 100.0f, float(FontStretch::kMax)));
 | |
| }
 | |
| 
 | |
| void Gecko_FontSlantStyle_SetNormal(mozilla::FontSlantStyle* aStyle) {
 | |
|   *aStyle = mozilla::FontSlantStyle::Normal();
 | |
| }
 | |
| 
 | |
| void Gecko_FontSlantStyle_SetItalic(mozilla::FontSlantStyle* aStyle) {
 | |
|   *aStyle = mozilla::FontSlantStyle::Italic();
 | |
| }
 | |
| 
 | |
| void Gecko_FontSlantStyle_SetOblique(mozilla::FontSlantStyle* aStyle,
 | |
|                                      float aAngleInDegrees) {
 | |
|   *aStyle = mozilla::FontSlantStyle::Oblique(aAngleInDegrees);
 | |
| }
 | |
| 
 | |
| void Gecko_FontSlantStyle_Get(mozilla::FontSlantStyle aStyle, bool* aNormal,
 | |
|                               bool* aItalic, float* aObliqueAngle) {
 | |
|   *aNormal = aStyle.IsNormal();
 | |
|   *aItalic = aStyle.IsItalic();
 | |
|   if (aStyle.IsOblique()) {
 | |
|     *aObliqueAngle = aStyle.ObliqueAngle();
 | |
|   }
 | |
| }
 | |
| 
 | |
| float Gecko_FontWeight_ToFloat(mozilla::FontWeight aWeight) {
 | |
|   return aWeight.ToFloat();
 | |
| }
 | |
| 
 | |
| void Gecko_FontWeight_SetFloat(mozilla::FontWeight* aWeight, float aFloat) {
 | |
|   *aWeight = mozilla::FontWeight(aFloat);
 | |
| }
 | |
| 
 | |
| void Gecko_nsFont_ResetFontFeatureValuesLookup(nsFont* aFont) {
 | |
|   aFont->featureValueLookup = nullptr;
 | |
| }
 | |
| 
 | |
| void Gecko_ClearAlternateValues(nsFont* aFont, size_t aLength) {
 | |
|   aFont->alternateValues.Clear();
 | |
|   aFont->alternateValues.SetCapacity(aLength);
 | |
| }
 | |
| 
 | |
| void Gecko_AppendAlternateValues(nsFont* aFont, uint32_t aAlternateName,
 | |
|                                  nsAtom* aAtom) {
 | |
|   aFont->alternateValues.AppendElement(
 | |
|       gfxAlternateValue{aAlternateName, nsDependentAtomString(aAtom)});
 | |
| }
 | |
| 
 | |
| void Gecko_CopyAlternateValuesFrom(nsFont* aDest, const nsFont* aSrc) {
 | |
|   aDest->alternateValues.Clear();
 | |
|   aDest->alternateValues.AppendElements(aSrc->alternateValues);
 | |
|   aDest->featureValueLookup = aSrc->featureValueLookup;
 | |
| }
 | |
| 
 | |
| void Gecko_SetCounterStyleToName(CounterStylePtr* aPtr, nsAtom* aName,
 | |
|                                  RawGeckoPresContextBorrowed aPresContext) {
 | |
|   RefPtr<nsAtom> name = already_AddRefed<nsAtom>(aName);
 | |
|   *aPtr = name.forget();
 | |
| }
 | |
| 
 | |
| void Gecko_SetCounterStyleToSymbols(CounterStylePtr* aPtr, uint8_t aSymbolsType,
 | |
|                                     nsACString const* const* aSymbols,
 | |
|                                     uint32_t aSymbolsCount) {
 | |
|   nsTArray<nsString> symbols(aSymbolsCount);
 | |
|   for (uint32_t i = 0; i < aSymbolsCount; i++) {
 | |
|     symbols.AppendElement(NS_ConvertUTF8toUTF16(*aSymbols[i]));
 | |
|   }
 | |
|   *aPtr = new AnonymousCounterStyle(aSymbolsType, std::move(symbols));
 | |
| }
 | |
| 
 | |
| void Gecko_SetCounterStyleToString(CounterStylePtr* aPtr,
 | |
|                                    const nsACString* aSymbol) {
 | |
|   *aPtr = new AnonymousCounterStyle(NS_ConvertUTF8toUTF16(*aSymbol));
 | |
| }
 | |
| 
 | |
| void Gecko_CopyCounterStyle(CounterStylePtr* aDst,
 | |
|                             const CounterStylePtr* aSrc) {
 | |
|   *aDst = *aSrc;
 | |
| }
 | |
| 
 | |
| nsAtom* Gecko_CounterStyle_GetName(const CounterStylePtr* aPtr) {
 | |
|   return aPtr->IsAtom() ? aPtr->AsAtom() : nullptr;
 | |
| }
 | |
| 
 | |
| const AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
 | |
|     const CounterStylePtr* aPtr) {
 | |
|   return aPtr->AsAnonymous();
 | |
| }
 | |
| 
 | |
| void Gecko_SetNullImageValue(nsStyleImage* aImage) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   aImage->SetNull();
 | |
| }
 | |
| 
 | |
| void Gecko_SetGradientImageValue(nsStyleImage* aImage,
 | |
|                                  nsStyleGradient* aGradient) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   aImage->SetGradientData(aGradient);
 | |
| }
 | |
| 
 | |
| static already_AddRefed<nsStyleImageRequest> CreateStyleImageRequest(
 | |
|     nsStyleImageRequest::Mode aModeFlags, URLValue* aImageValue) {
 | |
|   RefPtr<nsStyleImageRequest> req =
 | |
|       new nsStyleImageRequest(aModeFlags, aImageValue);
 | |
|   return req.forget();
 | |
| }
 | |
| 
 | |
| void Gecko_SetLayerImageImageValue(nsStyleImage* aImage,
 | |
|                                    URLValue* aImageValue) {
 | |
|   MOZ_ASSERT(aImage && aImageValue);
 | |
| 
 | |
|   RefPtr<nsStyleImageRequest> req =
 | |
|       CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aImageValue);
 | |
|   aImage->SetImageRequest(req.forget());
 | |
| }
 | |
| 
 | |
| void Gecko_SetImageElement(nsStyleImage* aImage, nsAtom* aAtom) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   aImage->SetElementId(do_AddRef(aAtom));
 | |
| }
 | |
| 
 | |
| void Gecko_CopyImageValueFrom(nsStyleImage* aImage,
 | |
|                               const nsStyleImage* aOther) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   MOZ_ASSERT(aOther);
 | |
| 
 | |
|   *aImage = *aOther;
 | |
| }
 | |
| 
 | |
| void Gecko_InitializeImageCropRect(nsStyleImage* aImage) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   aImage->SetCropRect(MakeUnique<nsStyleSides>());
 | |
| }
 | |
| 
 | |
| void Gecko_SetCursorArrayLength(nsStyleUI* aStyleUI, size_t aLen) {
 | |
|   aStyleUI->mCursorImages.Clear();
 | |
|   aStyleUI->mCursorImages.SetLength(aLen);
 | |
| }
 | |
| 
 | |
| void Gecko_SetCursorImageValue(nsCursorImage* aCursor, URLValue* aImageValue) {
 | |
|   MOZ_ASSERT(aCursor && aImageValue);
 | |
| 
 | |
|   aCursor->mImage =
 | |
|       CreateStyleImageRequest(nsStyleImageRequest::Mode::Discard, aImageValue);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyCursorArrayFrom(nsStyleUI* aDest, const nsStyleUI* aSrc) {
 | |
|   aDest->mCursorImages = aSrc->mCursorImages;
 | |
| }
 | |
| 
 | |
| void Gecko_SetContentDataImageValue(nsStyleContentData* aContent,
 | |
|                                     URLValue* aImageValue) {
 | |
|   MOZ_ASSERT(aContent && aImageValue);
 | |
| 
 | |
|   RefPtr<nsStyleImageRequest> req =
 | |
|       CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aImageValue);
 | |
|   aContent->SetImageRequest(req.forget());
 | |
| }
 | |
| 
 | |
| nsStyleContentData::CounterFunction* Gecko_SetCounterFunction(
 | |
|     nsStyleContentData* aContent, StyleContentType aType) {
 | |
|   auto counterFunc = MakeRefPtr<nsStyleContentData::CounterFunction>();
 | |
|   auto* ptr = counterFunc.get();
 | |
|   aContent->SetCounters(aType, counterFunc.forget());
 | |
|   return ptr;
 | |
| }
 | |
| 
 | |
| nsStyleGradient* Gecko_CreateGradient(uint8_t aShape, uint8_t aSize,
 | |
|                                       bool aRepeating, bool aLegacySyntax,
 | |
|                                       bool aMozLegacySyntax,
 | |
|                                       uint32_t aStopCount) {
 | |
|   nsStyleGradient* result = new nsStyleGradient();
 | |
| 
 | |
|   result->mShape = aShape;
 | |
|   result->mSize = aSize;
 | |
|   result->mRepeating = aRepeating;
 | |
|   result->mLegacySyntax = aLegacySyntax;
 | |
|   result->mMozLegacySyntax = aMozLegacySyntax;
 | |
| 
 | |
|   result->mAngle.SetNoneValue();
 | |
|   result->mBgPosX.SetNoneValue();
 | |
|   result->mBgPosY.SetNoneValue();
 | |
|   result->mRadiusX.SetNoneValue();
 | |
|   result->mRadiusY.SetNoneValue();
 | |
| 
 | |
|   nsStyleGradientStop dummyStop = {nsStyleCoord(eStyleUnit_None),
 | |
|                                    StyleComplexColor::Black(), 0};
 | |
| 
 | |
|   for (uint32_t i = 0; i < aStopCount; i++) {
 | |
|     result->mStops.AppendElement(dummyStop);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| const nsStyleImageRequest* Gecko_GetImageRequest(const nsStyleImage* aImage) {
 | |
|   MOZ_ASSERT(aImage);
 | |
|   return aImage->ImageRequest();
 | |
| }
 | |
| 
 | |
| nsAtom* Gecko_GetImageElement(const nsStyleImage* aImage) {
 | |
|   MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Element);
 | |
|   return const_cast<nsAtom*>(aImage->GetElementId());
 | |
| }
 | |
| 
 | |
| const nsStyleGradient* Gecko_GetGradientImageValue(const nsStyleImage* aImage) {
 | |
|   MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Gradient);
 | |
|   return aImage->GetGradientData();
 | |
| }
 | |
| 
 | |
| void Gecko_SetListStyleImageNone(nsStyleList* aList) {
 | |
|   aList->mListStyleImage = nullptr;
 | |
| }
 | |
| 
 | |
| void Gecko_SetListStyleImageImageValue(nsStyleList* aList,
 | |
|                                        URLValue* aImageValue) {
 | |
|   MOZ_ASSERT(aList && aImageValue);
 | |
| 
 | |
|   aList->mListStyleImage =
 | |
|       CreateStyleImageRequest(nsStyleImageRequest::Mode(0), aImageValue);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyListStyleImageFrom(nsStyleList* aList,
 | |
|                                   const nsStyleList* aSource) {
 | |
|   aList->mListStyleImage = aSource->mListStyleImage;
 | |
| }
 | |
| 
 | |
| void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
 | |
|                                 size_t aElemSize) {
 | |
|   auto base = reinterpret_cast<
 | |
|       nsTArray_base<nsTArrayInfallibleAllocator, nsTArray_CopyWithMemutils>*>(
 | |
|       aArray);
 | |
| 
 | |
|   base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
 | |
| }
 | |
| 
 | |
| void Gecko_ClearPODTArray(void* aArray, size_t aElementSize,
 | |
|                           size_t aElementAlign) {
 | |
|   auto base = reinterpret_cast<
 | |
|       nsTArray_base<nsTArrayInfallibleAllocator, nsTArray_CopyWithMemutils>*>(
 | |
|       aArray);
 | |
| 
 | |
|   base->template ShiftData<nsTArrayInfallibleAllocator>(
 | |
|       0, base->Length(), 0, aElementSize, aElementAlign);
 | |
| }
 | |
| 
 | |
| void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* aArray,
 | |
|                                   uint32_t aLength) {
 | |
|   aArray->SetLength(aLength);
 | |
| }
 | |
| 
 | |
| void Gecko_SetStyleGridTemplate(UniquePtr<nsStyleGridTemplate>* aGridTemplate,
 | |
|                                 nsStyleGridTemplate* aValue) {
 | |
|   aGridTemplate->reset(aValue);
 | |
| }
 | |
| 
 | |
| nsStyleGridTemplate* Gecko_CreateStyleGridTemplate(uint32_t aTrackSizes,
 | |
|                                                    uint32_t aNameSize) {
 | |
|   nsStyleGridTemplate* result = new nsStyleGridTemplate;
 | |
|   result->mMinTrackSizingFunctions.SetLength(aTrackSizes);
 | |
|   result->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
 | |
|   result->mLineNameLists.SetLength(aNameSize);
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| void Gecko_CopyStyleGridTemplateValues(
 | |
|     UniquePtr<nsStyleGridTemplate>* aGridTemplate,
 | |
|     const nsStyleGridTemplate* aOther) {
 | |
|   if (aOther) {
 | |
|     *aGridTemplate = MakeUnique<nsStyleGridTemplate>(*aOther);
 | |
|   } else {
 | |
|     *aGridTemplate = nullptr;
 | |
|   }
 | |
| }
 | |
| 
 | |
| GridTemplateAreasValue* Gecko_NewGridTemplateAreasValue(uint32_t aAreas,
 | |
|                                                         uint32_t aTemplates,
 | |
|                                                         uint32_t aColumns) {
 | |
|   RefPtr<GridTemplateAreasValue> value = new GridTemplateAreasValue;
 | |
|   value->mNamedAreas.SetLength(aAreas);
 | |
|   value->mTemplates.SetLength(aTemplates);
 | |
|   value->mNColumns = aColumns;
 | |
|   return value.forget().take();
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(GridTemplateAreasValue,
 | |
|                                    GridTemplateAreasValue);
 | |
| 
 | |
| void Gecko_ClearAndResizeStyleContents(nsStyleContent* aContent,
 | |
|                                        uint32_t aHowMany) {
 | |
|   aContent->AllocateContents(aHowMany);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyStyleContentsFrom(nsStyleContent* aContent,
 | |
|                                  const nsStyleContent* aOther) {
 | |
|   uint32_t count = aOther->ContentCount();
 | |
| 
 | |
|   aContent->AllocateContents(count);
 | |
| 
 | |
|   for (uint32_t i = 0; i < count; ++i) {
 | |
|     aContent->ContentAt(i) = aOther->ContentAt(i);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_ClearAndResizeCounterIncrements(nsStyleContent* aContent,
 | |
|                                            uint32_t aHowMany) {
 | |
|   aContent->AllocateCounterIncrements(aHowMany);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyCounterIncrementsFrom(nsStyleContent* aContent,
 | |
|                                      const nsStyleContent* aOther) {
 | |
|   uint32_t count = aOther->CounterIncrementCount();
 | |
| 
 | |
|   aContent->AllocateCounterIncrements(count);
 | |
| 
 | |
|   for (uint32_t i = 0; i < count; ++i) {
 | |
|     const nsStyleCounterData& data = aOther->CounterIncrementAt(i);
 | |
|     aContent->SetCounterIncrementAt(i, data.mCounter, data.mValue);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_ClearAndResizeCounterResets(nsStyleContent* aContent,
 | |
|                                        uint32_t aHowMany) {
 | |
|   aContent->AllocateCounterResets(aHowMany);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyCounterResetsFrom(nsStyleContent* aContent,
 | |
|                                  const nsStyleContent* aOther) {
 | |
|   uint32_t count = aOther->CounterResetCount();
 | |
| 
 | |
|   aContent->AllocateCounterResets(count);
 | |
| 
 | |
|   for (uint32_t i = 0; i < count; ++i) {
 | |
|     const nsStyleCounterData& data = aOther->CounterResetAt(i);
 | |
|     aContent->SetCounterResetAt(i, data.mCounter, data.mValue);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
 | |
|                                    nsStyleImageLayers::LayerType aLayerType) {
 | |
|   size_t oldLength = aLayers->mLayers.Length();
 | |
| 
 | |
|   aLayers->mLayers.EnsureLengthAtLeast(aLen);
 | |
| 
 | |
|   for (size_t i = oldLength; i < aLen; ++i) {
 | |
|     aLayers->mLayers[i].Initialize(aLayerType);
 | |
|   }
 | |
| }
 | |
| 
 | |
| template <typename StyleType>
 | |
| static void EnsureStyleAutoArrayLength(StyleType* aArray, size_t aLen) {
 | |
|   size_t oldLength = aArray->Length();
 | |
| 
 | |
|   aArray->EnsureLengthAtLeast(aLen);
 | |
| 
 | |
|   for (size_t i = oldLength; i < aLen; ++i) {
 | |
|     (*aArray)[i].SetInitialValues();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_EnsureStyleAnimationArrayLength(void* aArray, size_t aLen) {
 | |
|   auto base = static_cast<nsStyleAutoArray<StyleAnimation>*>(aArray);
 | |
|   EnsureStyleAutoArrayLength(base, aLen);
 | |
| }
 | |
| 
 | |
| void Gecko_EnsureStyleTransitionArrayLength(void* aArray, size_t aLen) {
 | |
|   auto base = reinterpret_cast<nsStyleAutoArray<StyleTransition>*>(aArray);
 | |
|   EnsureStyleAutoArrayLength(base, aLen);
 | |
| }
 | |
| 
 | |
| void Gecko_ClearWillChange(nsStyleDisplay* aDisplay, size_t aLength) {
 | |
|   aDisplay->mWillChange.Clear();
 | |
|   aDisplay->mWillChange.SetCapacity(aLength);
 | |
| }
 | |
| 
 | |
| void Gecko_AppendWillChange(nsStyleDisplay* aDisplay, nsAtom* aAtom) {
 | |
|   aDisplay->mWillChange.AppendElement(aAtom);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyWillChangeFrom(nsStyleDisplay* aDest, nsStyleDisplay* aSrc) {
 | |
|   aDest->mWillChange.Clear();
 | |
|   aDest->mWillChange.AppendElements(aSrc->mWillChange);
 | |
| }
 | |
| 
 | |
| enum class KeyframeSearchDirection {
 | |
|   Forwards,
 | |
|   Backwards,
 | |
| };
 | |
| 
 | |
| enum class KeyframeInsertPosition {
 | |
|   Prepend,
 | |
|   LastForOffset,
 | |
| };
 | |
| 
 | |
| static Keyframe* GetOrCreateKeyframe(nsTArray<Keyframe>* aKeyframes,
 | |
|                                      float aOffset,
 | |
|                                      const nsTimingFunction* aTimingFunction,
 | |
|                                      KeyframeSearchDirection aSearchDirection,
 | |
|                                      KeyframeInsertPosition aInsertPosition) {
 | |
|   MOZ_ASSERT(aKeyframes, "The keyframe array should be valid");
 | |
|   MOZ_ASSERT(aTimingFunction, "The timing function should be valid");
 | |
|   MOZ_ASSERT(aOffset >= 0. && aOffset <= 1.,
 | |
|              "The offset should be in the range of [0.0, 1.0]");
 | |
| 
 | |
|   size_t keyframeIndex;
 | |
|   switch (aSearchDirection) {
 | |
|     case KeyframeSearchDirection::Forwards:
 | |
|       if (nsAnimationManager::FindMatchingKeyframe(
 | |
|               *aKeyframes, aOffset, *aTimingFunction, keyframeIndex)) {
 | |
|         return &(*aKeyframes)[keyframeIndex];
 | |
|       }
 | |
|       break;
 | |
|     case KeyframeSearchDirection::Backwards:
 | |
|       if (nsAnimationManager::FindMatchingKeyframe(Reversed(*aKeyframes),
 | |
|                                                    aOffset, *aTimingFunction,
 | |
|                                                    keyframeIndex)) {
 | |
|         return &(*aKeyframes)[aKeyframes->Length() - 1 - keyframeIndex];
 | |
|       }
 | |
|       keyframeIndex = aKeyframes->Length() - 1;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   Keyframe* keyframe = aKeyframes->InsertElementAt(
 | |
|       aInsertPosition == KeyframeInsertPosition::Prepend ? 0 : keyframeIndex);
 | |
|   keyframe->mOffset.emplace(aOffset);
 | |
|   if (!aTimingFunction->IsLinear()) {
 | |
|     keyframe->mTimingFunction.emplace();
 | |
|     keyframe->mTimingFunction->Init(*aTimingFunction);
 | |
|   }
 | |
| 
 | |
|   return keyframe;
 | |
| }
 | |
| 
 | |
| Keyframe* Gecko_GetOrCreateKeyframeAtStart(
 | |
|     nsTArray<Keyframe>* aKeyframes, float aOffset,
 | |
|     const nsTimingFunction* aTimingFunction) {
 | |
|   MOZ_ASSERT(aKeyframes->IsEmpty() ||
 | |
|                  aKeyframes->ElementAt(0).mOffset.value() >= aOffset,
 | |
|              "The offset should be less than or equal to the first keyframe's "
 | |
|              "offset if there are exisiting keyframes");
 | |
| 
 | |
|   return GetOrCreateKeyframe(aKeyframes, aOffset, aTimingFunction,
 | |
|                              KeyframeSearchDirection::Forwards,
 | |
|                              KeyframeInsertPosition::Prepend);
 | |
| }
 | |
| 
 | |
| Keyframe* Gecko_GetOrCreateInitialKeyframe(
 | |
|     nsTArray<Keyframe>* aKeyframes, const nsTimingFunction* aTimingFunction) {
 | |
|   return GetOrCreateKeyframe(aKeyframes, 0., aTimingFunction,
 | |
|                              KeyframeSearchDirection::Forwards,
 | |
|                              KeyframeInsertPosition::LastForOffset);
 | |
| }
 | |
| 
 | |
| Keyframe* Gecko_GetOrCreateFinalKeyframe(
 | |
|     nsTArray<Keyframe>* aKeyframes, const nsTimingFunction* aTimingFunction) {
 | |
|   return GetOrCreateKeyframe(aKeyframes, 1., aTimingFunction,
 | |
|                              KeyframeSearchDirection::Backwards,
 | |
|                              KeyframeInsertPosition::LastForOffset);
 | |
| }
 | |
| 
 | |
| PropertyValuePair* Gecko_AppendPropertyValuePair(
 | |
|     nsTArray<PropertyValuePair>* aProperties, nsCSSPropertyID aProperty) {
 | |
|   MOZ_ASSERT(aProperties);
 | |
|   MOZ_ASSERT(aProperty == eCSSPropertyExtra_variable ||
 | |
|              !nsCSSProps::PropHasFlags(aProperty, CSSPropFlags::IsLogical));
 | |
|   return aProperties->AppendElement(PropertyValuePair{aProperty});
 | |
| }
 | |
| 
 | |
| void Gecko_ResetStyleCoord(nsStyleUnit* aUnit, nsStyleUnion* aValue) {
 | |
|   nsStyleCoord::Reset(*aUnit, *aValue);
 | |
| }
 | |
| 
 | |
| void Gecko_SetStyleCoordCalcValue(nsStyleUnit* aUnit, nsStyleUnion* aValue,
 | |
|                                   nsStyleCoord::CalcValue aCalc) {
 | |
|   // Calc units should be cleaned up first
 | |
|   MOZ_ASSERT(*aUnit != nsStyleUnit::eStyleUnit_Calc);
 | |
|   nsStyleCoord::Calc* calcRef = new nsStyleCoord::Calc();
 | |
|   calcRef->mLength = aCalc.mLength;
 | |
|   calcRef->mPercent = aCalc.mPercent;
 | |
|   calcRef->mHasPercent = aCalc.mHasPercent;
 | |
|   *aUnit = nsStyleUnit::eStyleUnit_Calc;
 | |
|   aValue->mPointer = calcRef;
 | |
|   calcRef->AddRef();
 | |
| }
 | |
| 
 | |
| void Gecko_CopyShapeSourceFrom(mozilla::StyleShapeSource* aDst,
 | |
|                                const mozilla::StyleShapeSource* aSrc) {
 | |
|   MOZ_ASSERT(aDst);
 | |
|   MOZ_ASSERT(aSrc);
 | |
| 
 | |
|   *aDst = *aSrc;
 | |
| }
 | |
| 
 | |
| void Gecko_DestroyShapeSource(mozilla::StyleShapeSource* aShape) {
 | |
|   aShape->~StyleShapeSource();
 | |
| }
 | |
| 
 | |
| void Gecko_StyleShapeSource_SetURLValue(StyleShapeSource* aShape,
 | |
|                                         URLValue* aURL) {
 | |
|   aShape->SetURL(*aURL);
 | |
| }
 | |
| 
 | |
| void Gecko_NewBasicShape(mozilla::StyleShapeSource* aShape,
 | |
|                          mozilla::StyleBasicShapeType aType) {
 | |
|   aShape->SetBasicShape(MakeUnique<mozilla::StyleBasicShape>(aType),
 | |
|                         StyleGeometryBox::NoBox);
 | |
| }
 | |
| 
 | |
| void Gecko_NewShapeImage(mozilla::StyleShapeSource* aShape) {
 | |
|   aShape->SetShapeImage(MakeUnique<nsStyleImage>());
 | |
| }
 | |
| 
 | |
| void Gecko_NewStyleSVGPath(mozilla::StyleShapeSource* aShape) {
 | |
|   MOZ_ASSERT(aShape);
 | |
|   aShape->SetPath(MakeUnique<mozilla::StyleSVGPath>());
 | |
| }
 | |
| 
 | |
| void Gecko_SetStyleMotion(UniquePtr<mozilla::StyleMotion>* aMotion,
 | |
|                           mozilla::StyleMotion* aValue) {
 | |
|   MOZ_ASSERT(aMotion);
 | |
|   aMotion->reset(aValue);
 | |
| }
 | |
| 
 | |
| mozilla::StyleMotion* Gecko_NewStyleMotion() { return new StyleMotion(); }
 | |
| 
 | |
| void Gecko_CopyStyleMotions(mozilla::UniquePtr<mozilla::StyleMotion>* aMotion,
 | |
|                             const mozilla::StyleMotion* aOther) {
 | |
|   MOZ_ASSERT(aMotion);
 | |
|   *aMotion = aOther ? MakeUnique<StyleMotion>(*aOther) : nullptr;
 | |
| }
 | |
| 
 | |
| void Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len) {
 | |
|   effects->mFilters.Clear();
 | |
|   effects->mFilters.SetLength(new_len);
 | |
| }
 | |
| 
 | |
| void Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest) {
 | |
|   aDest->mFilters = aSrc->mFilters;
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFilter_SetURLValue(nsStyleFilter* aEffects, URLValue* aURL) {
 | |
|   aEffects->SetURL(aURL);
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVGPaint_CopyFrom(nsStyleSVGPaint* aDest,
 | |
|                                     const nsStyleSVGPaint* aSrc) {
 | |
|   *aDest = *aSrc;
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVGPaint_SetURLValue(nsStyleSVGPaint* aPaint,
 | |
|                                        URLValue* aURL) {
 | |
|   aPaint->SetPaintServer(aURL);
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVGPaint_Reset(nsStyleSVGPaint* aPaint) { aPaint->SetNone(); }
 | |
| 
 | |
| void Gecko_nsStyleSVG_SetDashArrayLength(nsStyleSVG* aSvg, uint32_t aLen) {
 | |
|   aSvg->mStrokeDasharray.Clear();
 | |
|   aSvg->mStrokeDasharray.SetLength(aLen);
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVG_CopyDashArray(nsStyleSVG* aDst, const nsStyleSVG* aSrc) {
 | |
|   aDst->mStrokeDasharray = aSrc->mStrokeDasharray;
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVG_SetContextPropertiesLength(nsStyleSVG* aSvg,
 | |
|                                                  uint32_t aLen) {
 | |
|   aSvg->mContextProps.Clear();
 | |
|   aSvg->mContextProps.SetLength(aLen);
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleSVG_CopyContextProperties(nsStyleSVG* aDst,
 | |
|                                             const nsStyleSVG* aSrc) {
 | |
|   aDst->mContextProps = aSrc->mContextProps;
 | |
|   aDst->mContextPropsBits = aSrc->mContextPropsBits;
 | |
| }
 | |
| 
 | |
| css::URLValue* Gecko_URLValue_Create(RawServoCssUrlDataStrong aCssUrl,
 | |
|                                      CORSMode aCORSMode) {
 | |
|   RefPtr<css::URLValue> url = new css::URLValue(aCssUrl.Consume(), aCORSMode);
 | |
|   return url.forget().take();
 | |
| }
 | |
| 
 | |
| MOZ_DEFINE_MALLOC_SIZE_OF(GeckoURLValueMallocSizeOf)
 | |
| 
 | |
| size_t Gecko_URLValue_SizeOfIncludingThis(URLValue* aURL) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   return aURL->SizeOfIncludingThis(GeckoURLValueMallocSizeOf);
 | |
| }
 | |
| 
 | |
| void Gecko_GetComputedURLSpec(const URLValue* aURL, nsCString* aOut) {
 | |
|   MOZ_ASSERT(aURL);
 | |
|   MOZ_ASSERT(aOut);
 | |
|   if (aURL->IsLocalRef()) {
 | |
|     aOut->Assign(aURL->GetString());
 | |
|     return;
 | |
|   }
 | |
|   Gecko_GetComputedImageURLSpec(aURL, aOut);
 | |
| }
 | |
| 
 | |
| void Gecko_GetComputedImageURLSpec(const URLValue* aURL, nsCString* aOut) {
 | |
|   // Image URIs don't serialize local refs as local.
 | |
|   if (nsIURI* uri = aURL->GetURI()) {
 | |
|     nsresult rv = uri->GetSpec(*aOut);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   aOut->AssignLiteral("about:invalid");
 | |
| }
 | |
| 
 | |
| void Gecko_nsIURI_Debug(nsIURI* aURI, nsCString* aOut) {
 | |
|   // TODO(emilio): Do we have more useful stuff to put here, maybe?
 | |
|   if (aURI) {
 | |
|     *aOut = aURI->GetSpecOrDefault();
 | |
|   }
 | |
| }
 | |
| 
 | |
| template <typename ElementLike>
 | |
| void DebugListAttributes(const ElementLike& aElement, nsCString& aOut) {
 | |
|   const uint32_t kMaxAttributeLength = 40;
 | |
| 
 | |
|   uint32_t i = 0;
 | |
|   while (BorrowedAttrInfo info = aElement.GetAttrInfoAt(i++)) {
 | |
|     aOut.AppendLiteral(" ");
 | |
|     if (nsAtom* prefix = info.mName->GetPrefix()) {
 | |
|       aOut.Append(NS_ConvertUTF16toUTF8(nsDependentAtomString(prefix)));
 | |
|       aOut.AppendLiteral(":");
 | |
|     }
 | |
|     aOut.Append(
 | |
|         NS_ConvertUTF16toUTF8(nsDependentAtomString(info.mName->LocalName())));
 | |
|     if (!info.mValue) {
 | |
|       continue;
 | |
|     }
 | |
|     aOut.AppendLiteral("=\"");
 | |
|     nsAutoString value;
 | |
|     info.mValue->ToString(value);
 | |
|     if (value.Length() > kMaxAttributeLength) {
 | |
|       value.Truncate(kMaxAttributeLength - 3);
 | |
|       value.AppendLiteral("...");
 | |
|     }
 | |
|     aOut.Append(NS_ConvertUTF16toUTF8(value));
 | |
|     aOut.AppendLiteral("\"");
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_Element_DebugListAttributes(RawGeckoElementBorrowed aElement,
 | |
|                                        nsCString* aOut) {
 | |
|   DebugListAttributes(*aElement, *aOut);
 | |
| }
 | |
| 
 | |
| void Gecko_Snapshot_DebugListAttributes(const ServoElementSnapshot* aSnapshot,
 | |
|                                         nsCString* aOut) {
 | |
|   DebugListAttributes(*aSnapshot, *aOut);
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(css::URLValue, CSSURLValue);
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(URLExtraData, URLExtraData);
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
 | |
| 
 | |
| nsCSSShadowArray* Gecko_NewCSSShadowArray(uint32_t aLen) {
 | |
|   RefPtr<nsCSSShadowArray> arr = new (aLen) nsCSSShadowArray(aLen);
 | |
|   return arr.forget().take();
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
 | |
| 
 | |
| nsCSSValueSharedList* Gecko_NewCSSValueSharedList(uint32_t aLen) {
 | |
|   RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
 | |
|   if (aLen == 0) {
 | |
|     return list.forget().take();
 | |
|   }
 | |
| 
 | |
|   list->mHead = new nsCSSValueList;
 | |
|   nsCSSValueList* cur = list->mHead;
 | |
|   for (uint32_t i = 0; i < aLen - 1; i++) {
 | |
|     cur->mNext = new nsCSSValueList;
 | |
|     cur = cur->mNext;
 | |
|   }
 | |
| 
 | |
|   return list.forget().take();
 | |
| }
 | |
| 
 | |
| nsCSSValueSharedList* Gecko_NewNoneTransform() {
 | |
|   RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
 | |
|   list->mHead = new nsCSSValueList;
 | |
|   list->mHead->mValue.SetNoneValue();
 | |
|   return list.forget().take();
 | |
| }
 | |
| 
 | |
| void Gecko_StyleDisplay_GenerateCombinedTransform(nsStyleDisplay* aDisplay) {
 | |
|   aDisplay->GenerateCombinedIndividualTransform();
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue, float aNumber) {
 | |
|   aCSSValue->SetFloatValue(aNumber, eCSSUnit_Number);
 | |
| }
 | |
| 
 | |
| float Gecko_CSSValue_GetNumber(nsCSSValueBorrowed aCSSValue) {
 | |
|   return aCSSValue->GetFloatValue();
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                nsCSSKeyword aKeyword) {
 | |
|   aCSSValue->SetEnumValue(aKeyword);
 | |
| }
 | |
| 
 | |
| nsCSSKeyword Gecko_CSSValue_GetKeyword(nsCSSValueBorrowed aCSSValue) {
 | |
|   return aCSSValue->GetKeywordValue();
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                   float aPercent) {
 | |
|   aCSSValue->SetPercentValue(aPercent);
 | |
| }
 | |
| 
 | |
| float Gecko_CSSValue_GetPercentage(nsCSSValueBorrowed aCSSValue) {
 | |
|   return aCSSValue->GetPercentValue();
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetPixelLength(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                    float aLen) {
 | |
|   MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null ||
 | |
|              aCSSValue->GetUnit() == eCSSUnit_Pixel);
 | |
|   aCSSValue->SetFloatValue(aLen, eCSSUnit_Pixel);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue,
 | |
|                             nsStyleCoord::CalcValue aCalc) {
 | |
|   aCSSValue->SetCalcValue(aCalc);
 | |
| }
 | |
| 
 | |
| nsStyleCoord::CalcValue Gecko_CSSValue_GetCalc(nsCSSValueBorrowed aCSSValue) {
 | |
|   return aCSSValue->GetCalcValue();
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue, int32_t aLen) {
 | |
|   nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen);
 | |
|   aCSSValue->SetArrayValue(arr, eCSSUnit_Function);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetString(nsCSSValueBorrowedMut aCSSValue,
 | |
|                               const uint8_t* aString, uint32_t aLength,
 | |
|                               nsCSSUnit aUnit) {
 | |
|   MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null);
 | |
|   nsString string;
 | |
|   nsDependentCSubstring slice(reinterpret_cast<const char*>(aString), aLength);
 | |
|   AppendUTF8toUTF16(slice, string);
 | |
|   aCSSValue->SetStringValue(string, aUnit);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetStringFromAtom(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                       nsAtom* aAtom, nsCSSUnit aUnit) {
 | |
|   aCSSValue->SetStringValue(nsDependentAtomString(aAtom), aUnit);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetAtomIdent(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                  nsAtom* aAtom) {
 | |
|   aCSSValue->SetAtomIdentValue(already_AddRefed<nsAtom>(aAtom));
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetArray(nsCSSValueBorrowedMut aCSSValue, int32_t aLength) {
 | |
|   MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null);
 | |
|   RefPtr<nsCSSValue::Array> array = nsCSSValue::Array::Create(aLength);
 | |
|   aCSSValue->SetArrayValue(array, eCSSUnit_Array);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetInt(nsCSSValueBorrowedMut aCSSValue, int32_t aInteger,
 | |
|                            nsCSSUnit aUnit) {
 | |
|   aCSSValue->SetIntValue(aInteger, aUnit);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetFloat(nsCSSValueBorrowedMut aCSSValue, float aValue,
 | |
|                              nsCSSUnit aUnit) {
 | |
|   aCSSValue->SetFloatValue(aValue, aUnit);
 | |
| }
 | |
| 
 | |
| nsCSSValueBorrowedMut Gecko_CSSValue_GetArrayItem(
 | |
|     nsCSSValueBorrowedMut aCSSValue, int32_t aIndex) {
 | |
|   return &aCSSValue->GetArrayValue()->Item(aIndex);
 | |
| }
 | |
| 
 | |
| nsCSSValueBorrowed Gecko_CSSValue_GetArrayItemConst(
 | |
|     nsCSSValueBorrowed aCSSValue, int32_t aIndex) {
 | |
|   return &aCSSValue->GetArrayValue()->Item(aIndex);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetPair(nsCSSValueBorrowedMut aCSSValue,
 | |
|                             nsCSSValueBorrowed aXValue,
 | |
|                             nsCSSValueBorrowed aYValue) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   aCSSValue->SetPairValue(*aXValue, *aYValue);
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetList(nsCSSValueBorrowedMut aCSSValue, uint32_t aLen) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   nsCSSValueList* item = aCSSValue->SetListValue();
 | |
|   for (uint32_t i = 1; i < aLen; ++i) {
 | |
|     item->mNext = new nsCSSValueList;
 | |
|     item = item->mNext;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_SetPairList(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                 uint32_t aLen) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   nsCSSValuePairList* item = aCSSValue->SetPairListValue();
 | |
|   for (uint32_t i = 1; i < aLen; ++i) {
 | |
|     item->mNext = new nsCSSValuePairList;
 | |
|     item = item->mNext;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_InitSharedList(nsCSSValueBorrowedMut aCSSValue,
 | |
|                                    uint32_t aLen) {
 | |
|   MOZ_ASSERT(aLen > 0, "Must create at least one nsCSSValueList (mHead)");
 | |
| 
 | |
|   nsCSSValueSharedList* list = new nsCSSValueSharedList;
 | |
|   aCSSValue->SetSharedListValue(list);
 | |
|   list->mHead = new nsCSSValueList;
 | |
|   nsCSSValueList* cur = list->mHead;
 | |
|   for (uint32_t i = 1; i < aLen; ++i) {
 | |
|     cur->mNext = new nsCSSValueList;
 | |
|     cur = cur->mNext;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_CSSValue_Drop(nsCSSValueBorrowedMut aCSSValue) {
 | |
|   aCSSValue->~nsCSSValue();
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFont_SetLang(nsStyleFont* aFont, nsAtom* aAtom) {
 | |
|   aFont->mLanguage = dont_AddRef(aAtom);
 | |
|   aFont->mExplicitLanguage = true;
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont,
 | |
|                                     const nsStyleFont* aSource) {
 | |
|   aFont->mLanguage = aSource->mLanguage;
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFont_FixupNoneGeneric(
 | |
|     nsStyleFont* aFont, RawGeckoPresContextBorrowed aPresContext) {
 | |
|   const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper(
 | |
|       aPresContext, aFont->mLanguage, kPresContext_DefaultVariableFont_ID);
 | |
|   nsLayoutUtils::FixupNoneGeneric(&aFont->mFont, aPresContext,
 | |
|                                   aFont->mGenericID, defaultVariableFont);
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFont_PrefillDefaultForGeneric(
 | |
|     nsStyleFont* aFont, RawGeckoPresContextBorrowed aPresContext,
 | |
|     uint8_t aGenericId) {
 | |
|   const nsFont* defaultFont = ThreadSafeGetDefaultFontHelper(
 | |
|       aPresContext, aFont->mLanguage, aGenericId);
 | |
|   // In case of just the language changing, the parent could have had no
 | |
|   // generic, which Gecko just does regular cascading with. Do the same. This
 | |
|   // can only happen in the case where the language changed but the family did
 | |
|   // not
 | |
|   if (aGenericId != kGenericFont_NONE) {
 | |
|     aFont->mFont.fontlist = defaultFont->fontlist;
 | |
|   } else {
 | |
|     aFont->mFont.fontlist.SetDefaultFontType(
 | |
|         defaultFont->fontlist.GetDefaultFontType());
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Gecko_nsStyleFont_FixupMinFontSize(
 | |
|     nsStyleFont* aFont, RawGeckoPresContextBorrowed aPresContext) {
 | |
|   nscoord minFontSize;
 | |
|   bool needsCache = false;
 | |
| 
 | |
|   auto MinFontSize = [&](bool* aNeedsToCache) {
 | |
|     auto* prefs = aPresContext->Document()->GetFontPrefsForLang(
 | |
|         aFont->mLanguage, aNeedsToCache);
 | |
|     return prefs ? prefs->mMinimumFontSize : 0;
 | |
|   };
 | |
| 
 | |
|   {
 | |
|     AutoReadLock guard(*sServoFFILock);
 | |
|     minFontSize = MinFontSize(&needsCache);
 | |
|   }
 | |
| 
 | |
|   if (needsCache) {
 | |
|     AutoWriteLock guard(*sServoFFILock);
 | |
|     minFontSize = MinFontSize(nullptr);
 | |
|   }
 | |
| 
 | |
|   nsLayoutUtils::ApplyMinFontSize(aFont, aPresContext, minFontSize);
 | |
| }
 | |
| 
 | |
| void FontSizePrefs::CopyFrom(const LangGroupFontPrefs& prefs) {
 | |
|   mDefaultVariableSize = prefs.mDefaultVariableFont.size;
 | |
|   mDefaultFixedSize = prefs.mDefaultFixedFont.size;
 | |
|   mDefaultSerifSize = prefs.mDefaultSerifFont.size;
 | |
|   mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
 | |
|   mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
 | |
|   mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
 | |
|   mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
 | |
| }
 | |
| 
 | |
| FontSizePrefs Gecko_GetBaseSize(nsAtom* aLanguage) {
 | |
|   LangGroupFontPrefs prefs;
 | |
|   RefPtr<nsAtom> langGroupAtom =
 | |
|       StaticPresData::Get()->GetUncachedLangGroup(aLanguage);
 | |
| 
 | |
|   prefs.Initialize(langGroupAtom);
 | |
|   FontSizePrefs sizes;
 | |
|   sizes.CopyFrom(prefs);
 | |
| 
 | |
|   return sizes;
 | |
| }
 | |
| 
 | |
| RawGeckoElementBorrowedOrNull Gecko_GetBindingParent(
 | |
|     RawGeckoElementBorrowed aElement) {
 | |
|   nsIContent* parent = aElement->GetBindingParent();
 | |
|   return parent ? parent->AsElement() : nullptr;
 | |
| }
 | |
| 
 | |
| RawServoAuthorStylesBorrowedOrNull Gecko_XBLBinding_GetRawServoStyles(
 | |
|     RawGeckoXBLBindingBorrowed aXBLBinding) {
 | |
|   return aXBLBinding->GetServoStyles();
 | |
| }
 | |
| 
 | |
| bool Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding) {
 | |
|   return aXBLBinding->InheritsStyle();
 | |
| }
 | |
| 
 | |
| static StaticRefPtr<UACacheReporter> gUACacheReporter;
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| void InitializeServo() {
 | |
|   URLExtraData::InitDummy();
 | |
|   Servo_Initialize(URLExtraData::Dummy());
 | |
| 
 | |
|   gUACacheReporter = new UACacheReporter();
 | |
|   RegisterWeakMemoryReporter(gUACacheReporter);
 | |
| 
 | |
|   sServoFFILock = new RWLock("Servo::FFILock");
 | |
| }
 | |
| 
 | |
| void ShutdownServo() {
 | |
|   MOZ_ASSERT(sServoFFILock);
 | |
| 
 | |
|   UnregisterWeakMemoryReporter(gUACacheReporter);
 | |
|   gUACacheReporter = nullptr;
 | |
| 
 | |
|   delete sServoFFILock;
 | |
|   Servo_Shutdown();
 | |
| }
 | |
| 
 | |
| void AssertIsMainThreadOrServoFontMetricsLocked() {
 | |
|   if (!NS_IsMainThread()) {
 | |
|     MOZ_ASSERT(sServoFFILock &&
 | |
|                sServoFFILock->LockedForWritingByCurrentThread());
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| GeckoFontMetrics Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext,
 | |
|                                       bool aIsVertical,
 | |
|                                       const nsStyleFont* aFont,
 | |
|                                       nscoord aFontSize, bool aUseUserFontSet) {
 | |
|   AutoWriteLock guard(*sServoFFILock);
 | |
|   GeckoFontMetrics ret;
 | |
| 
 | |
|   // Getting font metrics can require some main thread only work to be
 | |
|   // done, such as work that needs to touch non-threadsafe refcounted
 | |
|   // objects (like the DOM FontFace/FontFaceSet objects), network loads, etc.
 | |
|   //
 | |
|   // To handle this work, font code checks whether we are in a Servo traversal
 | |
|   // and if so, appends PostTraversalTasks to the current ServoStyleSet
 | |
|   // to be performed immediately after the traversal is finished.  This
 | |
|   // works well for starting downloadable font loads, since we don't have
 | |
|   // those fonts available to get metrics for anyway.  Platform fonts and
 | |
|   // ArrayBuffer-backed FontFace objects are handled synchronously.
 | |
| 
 | |
|   nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
 | |
|   presContext->SetUsesExChUnits(true);
 | |
|   RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor(
 | |
|       presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet);
 | |
| 
 | |
|   ret.mXSize = fm->XHeight();
 | |
|   gfxFloat zeroWidth = fm->GetThebesFontGroup()
 | |
|                            ->GetFirstValidFont()
 | |
|                            ->GetMetrics(fm->Orientation())
 | |
|                            .zeroOrAveCharWidth;
 | |
|   ret.mChSize = NS_round(aPresContext->AppUnitsPerDevPixel() * zeroWidth);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int32_t Gecko_GetAppUnitsPerPhysicalInch(
 | |
|     RawGeckoPresContextBorrowed aPresContext) {
 | |
|   nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
 | |
|   return presContext->DeviceContext()->AppUnitsPerPhysicalInch();
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(SheetLoadDataHolder, SheetLoadDataHolder);
 | |
| 
 | |
| void Gecko_StyleSheet_FinishAsyncParse(
 | |
|     SheetLoadDataHolder* aData, RawServoStyleSheetContentsStrong aSheetContents,
 | |
|     StyleUseCountersOwned aUseCounters) {
 | |
|   UniquePtr<StyleUseCounters> useCounters(aUseCounters);
 | |
|   RefPtr<SheetLoadDataHolder> loadData = aData;
 | |
|   RefPtr<RawServoStyleSheetContents> sheetContents = aSheetContents.Consume();
 | |
|   NS_DispatchToMainThread(NS_NewRunnableFunction(
 | |
|       __func__, [d = std::move(loadData), contents = std::move(sheetContents),
 | |
|                  counters = std::move(useCounters)]() mutable {
 | |
|         MOZ_ASSERT(NS_IsMainThread());
 | |
|         SheetLoadData* data = d->get();
 | |
|         if (Document* doc = data->mLoader->GetDocument()) {
 | |
|           if (const StyleUseCounters* docCounters =
 | |
|                   doc->GetStyleUseCounters()) {
 | |
|             Servo_UseCounters_Merge(docCounters, counters.get());
 | |
|           }
 | |
|         }
 | |
|         data->mSheet->FinishAsyncParse(contents.forget());
 | |
|       }));
 | |
| }
 | |
| 
 | |
| static already_AddRefed<StyleSheet> LoadImportSheet(
 | |
|     css::Loader* aLoader, StyleSheet* aParent, SheetLoadData* aParentLoadData,
 | |
|     css::LoaderReusableStyleSheets* aReusableSheets, css::URLValue* aURL,
 | |
|     already_AddRefed<RawServoMediaList> aMediaList) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(aLoader, "Should've catched this before");
 | |
|   MOZ_ASSERT(aParent, "Only used for @import, so parent should exist!");
 | |
|   MOZ_ASSERT(aURL, "Invalid URLs shouldn't be loaded!");
 | |
| 
 | |
|   RefPtr<dom::MediaList> media = new MediaList(std::move(aMediaList));
 | |
|   nsCOMPtr<nsIURI> uri = aURL->GetURI();
 | |
|   nsresult rv = uri ? NS_OK : NS_ERROR_FAILURE;
 | |
| 
 | |
|   StyleSheet* previousFirstChild = aParent->GetFirstChild();
 | |
|   if (NS_SUCCEEDED(rv)) {
 | |
|     rv = aLoader->LoadChildSheet(aParent, aParentLoadData, uri, media,
 | |
|                                  aReusableSheets);
 | |
|   }
 | |
| 
 | |
|   if (NS_FAILED(rv) || !aParent->GetFirstChild() ||
 | |
|       aParent->GetFirstChild() == previousFirstChild) {
 | |
|     // Servo and Gecko have different ideas of what a valid URL is, so we might
 | |
|     // get in here with a URL string that NS_NewURI can't handle.  We may also
 | |
|     // reach here via an import cycle.  For the import cycle case, we need some
 | |
|     // sheet object per spec, even if its empty.  DevTools uses the URI to
 | |
|     // realize it has hit an import cycle, so we mark it complete to make the
 | |
|     // sheet readable from JS.
 | |
|     RefPtr<StyleSheet> emptySheet =
 | |
|         aParent->CreateEmptyChildSheet(media.forget());
 | |
|     // Make a dummy URI if we don't have one because some methods assume
 | |
|     // non-null URIs.
 | |
|     if (!uri) {
 | |
|       NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:invalid"));
 | |
|     }
 | |
|     emptySheet->SetURIs(uri, uri, uri);
 | |
|     emptySheet->SetPrincipal(aURL->ExtraData()->Principal());
 | |
|     emptySheet->SetComplete();
 | |
|     aParent->PrependStyleSheet(emptySheet);
 | |
|     return emptySheet.forget();
 | |
|   }
 | |
| 
 | |
|   RefPtr<StyleSheet> sheet = static_cast<StyleSheet*>(aParent->GetFirstChild());
 | |
|   return sheet.forget();
 | |
| }
 | |
| 
 | |
| StyleSheet* Gecko_LoadStyleSheet(
 | |
|     css::Loader* aLoader, StyleSheet* aParent, SheetLoadData* aParentLoadData,
 | |
|     css::LoaderReusableStyleSheets* aReusableSheets,
 | |
|     RawServoCssUrlDataStrong aCssUrl, RawServoMediaListStrong aMediaList) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   // The CORS mode in the URLValue is irrelevant here.
 | |
|   // (CORS_NONE is used for all imported sheets in Load::LoadChildSheet.)
 | |
|   RefPtr<css::URLValue> url = new css::URLValue(aCssUrl.Consume(), CORS_NONE);
 | |
|   return LoadImportSheet(aLoader, aParent, aParentLoadData, aReusableSheets,
 | |
|                          url, aMediaList.Consume())
 | |
|       .take();
 | |
| }
 | |
| 
 | |
| void Gecko_LoadStyleSheetAsync(css::SheetLoadDataHolder* aParentData,
 | |
|                                RawServoCssUrlDataStrong aCssUrl,
 | |
|                                RawServoMediaListStrong aMediaList,
 | |
|                                RawServoImportRuleStrong aImportRule) {
 | |
|   RefPtr<SheetLoadDataHolder> loadData = aParentData;
 | |
|   // The CORS mode in the URLValue is irrelevant here.
 | |
|   // (CORS_NONE is used for all imported sheets in Load::LoadChildSheet.)
 | |
|   RefPtr<css::URLValue> urlVal =
 | |
|       new css::URLValue(aCssUrl.Consume(), CORS_NONE);
 | |
|   RefPtr<RawServoMediaList> mediaList = aMediaList.Consume();
 | |
|   RefPtr<RawServoImportRule> importRule = aImportRule.Consume();
 | |
|   NS_DispatchToMainThread(NS_NewRunnableFunction(
 | |
|       __func__,
 | |
|       [data = std::move(loadData), url = std::move(urlVal),
 | |
|        media = std::move(mediaList), import = std::move(importRule)]() mutable {
 | |
|         MOZ_ASSERT(NS_IsMainThread());
 | |
|         SheetLoadData* d = data->get();
 | |
|         RefPtr<StyleSheet> sheet = LoadImportSheet(
 | |
|             d->mLoader, d->mSheet, d, nullptr, url, media.forget());
 | |
|         Servo_ImportRule_SetSheet(import, sheet);
 | |
|       }));
 | |
| }
 | |
| 
 | |
| nsCSSKeyword Gecko_LookupCSSKeyword(const uint8_t* aString, uint32_t aLength) {
 | |
|   nsDependentCSubstring keyword(reinterpret_cast<const char*>(aString),
 | |
|                                 aLength);
 | |
|   return nsCSSKeywords::LookupKeyword(keyword);
 | |
| }
 | |
| 
 | |
| const char* Gecko_CSSKeywordString(nsCSSKeyword aKeyword, uint32_t* aLength) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(aLength);
 | |
|   const nsCString& value = nsCSSKeywords::GetStringValue(aKeyword);
 | |
|   *aLength = value.Length();
 | |
|   return value.get();
 | |
| }
 | |
| 
 | |
| void Gecko_AddPropertyToSet(nsCSSPropertyIDSetBorrowedMut aPropertySet,
 | |
|                             nsCSSPropertyID aProperty) {
 | |
|   aPropertySet->AddProperty(aProperty);
 | |
| }
 | |
| 
 | |
| NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 | |
| 
 | |
| #define STYLE_STRUCT(name)                                             \
 | |
|                                                                        \
 | |
|   void Gecko_Construct_Default_nsStyle##name(                          \
 | |
|       nsStyle##name* ptr, const nsPresContext* pres_context) {         \
 | |
|     new (ptr) nsStyle##name(*pres_context->Document());                \
 | |
|   }                                                                    \
 | |
|                                                                        \
 | |
|   void Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr,           \
 | |
|                                          const nsStyle##name* other) { \
 | |
|     new (ptr) nsStyle##name(*other);                                   \
 | |
|   }                                                                    \
 | |
|                                                                        \
 | |
|   void Gecko_Destroy_nsStyle##name(nsStyle##name* ptr) {               \
 | |
|     ptr->~nsStyle##name();                                             \
 | |
|   }
 | |
| 
 | |
| void Gecko_RegisterProfilerThread(const char* name) {
 | |
|   PROFILER_REGISTER_THREAD(name);
 | |
| }
 | |
| 
 | |
| void Gecko_UnregisterProfilerThread() { PROFILER_UNREGISTER_THREAD(); }
 | |
| 
 | |
| bool Gecko_DocumentRule_UseForPresentation(
 | |
|     RawGeckoPresContextBorrowed aPresContext, const nsACString* aPattern,
 | |
|     css::DocumentMatchingFunction aMatchingFunction) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   Document* doc = aPresContext->Document();
 | |
|   nsIURI* docURI = doc->GetDocumentURI();
 | |
|   nsAutoCString docURISpec;
 | |
|   if (docURI) {
 | |
|     // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
 | |
|     nsresult rv = docURI->GetSpec(docURISpec);
 | |
|     NS_ENSURE_SUCCESS(rv, false);
 | |
|   }
 | |
| 
 | |
|   return CSSMozDocumentRule::Match(doc, docURI, docURISpec, *aPattern,
 | |
|                                    aMatchingFunction);
 | |
| }
 | |
| 
 | |
| void Gecko_SetJemallocThreadLocalArena(bool enabled) {
 | |
| #if defined(MOZ_MEMORY)
 | |
|   jemalloc_thread_local_arena(enabled);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #include "nsStyleStructList.h"
 | |
| 
 | |
| #undef STYLE_STRUCT
 | |
| 
 | |
| bool Gecko_ErrorReportingEnabled(const StyleSheet* aSheet,
 | |
|                                  const Loader* aLoader) {
 | |
|   return ErrorReporter::ShouldReportErrors(aSheet, aLoader);
 | |
| }
 | |
| 
 | |
| void Gecko_ReportUnexpectedCSSError(const StyleSheet* aSheet,
 | |
|                                     const Loader* aLoader, nsIURI* aURI,
 | |
|                                     const char* message, const char* param,
 | |
|                                     uint32_t paramLen, const char* prefix,
 | |
|                                     const char* prefixParam,
 | |
|                                     uint32_t prefixParamLen, const char* suffix,
 | |
|                                     const char* source, uint32_t sourceLen,
 | |
|                                     uint32_t lineNumber, uint32_t colNumber) {
 | |
|   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   ErrorReporter reporter(aSheet, aLoader, aURI);
 | |
| 
 | |
|   if (prefix) {
 | |
|     if (prefixParam) {
 | |
|       nsDependentCSubstring paramValue(prefixParam, prefixParamLen);
 | |
|       nsAutoString wideParam = NS_ConvertUTF8toUTF16(paramValue);
 | |
|       reporter.ReportUnexpectedUnescaped(prefix, wideParam);
 | |
|     } else {
 | |
|       reporter.ReportUnexpected(prefix);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (param) {
 | |
|     nsDependentCSubstring paramValue(param, paramLen);
 | |
|     nsAutoString wideParam = NS_ConvertUTF8toUTF16(paramValue);
 | |
|     reporter.ReportUnexpectedUnescaped(message, wideParam);
 | |
|   } else {
 | |
|     reporter.ReportUnexpected(message);
 | |
|   }
 | |
| 
 | |
|   if (suffix) {
 | |
|     reporter.ReportUnexpected(suffix);
 | |
|   }
 | |
|   nsDependentCSubstring sourceValue(source, sourceLen);
 | |
|   reporter.OutputError(lineNumber, colNumber, sourceValue);
 | |
| }
 | |
| 
 | |
| void Gecko_AddBufferToCrashReport(const void* addr, size_t len) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   nsCOMPtr<nsICrashReporter> cr =
 | |
|       do_GetService("@mozilla.org/toolkit/crash-reporter;1");
 | |
|   NS_ENSURE_TRUE_VOID(cr);
 | |
|   cr->RegisterAppMemory((uint64_t)addr, len);
 | |
| }
 | |
| 
 | |
| void Gecko_AnnotateCrashReport(const char* key_str, const char* value_str) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   nsDependentCString key(key_str);
 | |
|   nsDependentCString value(value_str);
 | |
|   nsCOMPtr<nsICrashReporter> cr =
 | |
|       do_GetService("@mozilla.org/toolkit/crash-reporter;1");
 | |
|   NS_ENSURE_TRUE_VOID(cr);
 | |
|   cr->AnnotateCrashReport(key, value);
 | |
| }
 | |
| 
 | |
| void Gecko_ContentList_AppendAll(nsSimpleContentList* aList,
 | |
|                                  const Element** aElements, size_t aLength) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   MOZ_ASSERT(aElements);
 | |
|   MOZ_ASSERT(aLength);
 | |
|   MOZ_ASSERT(aList);
 | |
| 
 | |
|   aList->SetCapacity(aLength);
 | |
| 
 | |
|   for (size_t i = 0; i < aLength; ++i) {
 | |
|     aList->AppendElement(const_cast<Element*>(aElements[i]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| const nsTArray<Element*>* Gecko_Document_GetElementsWithId(const Document* aDoc,
 | |
|                                                            nsAtom* aId) {
 | |
|   MOZ_ASSERT(aDoc);
 | |
|   MOZ_ASSERT(aId);
 | |
| 
 | |
|   return aDoc->GetAllElementsForId(nsDependentAtomString(aId));
 | |
| }
 | |
| 
 | |
| const nsTArray<Element*>* Gecko_ShadowRoot_GetElementsWithId(
 | |
|     const ShadowRoot* aShadowRoot, nsAtom* aId) {
 | |
|   MOZ_ASSERT(aShadowRoot);
 | |
|   MOZ_ASSERT(aId);
 | |
| 
 | |
|   return aShadowRoot->GetAllElementsForId(nsDependentAtomString(aId));
 | |
| }
 | |
| 
 | |
| bool Gecko_GetBoolPrefValue(const char* aPrefName) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
|   return Preferences::GetBool(aPrefName);
 | |
| }
 | |
| 
 | |
| bool Gecko_IsInServoTraversal() { return ServoStyleSet::IsInServoTraversal(); }
 | |
| 
 | |
| bool Gecko_IsMainThread() { return NS_IsMainThread(); }
 | |
| 
 | |
| const nsAttrValue* Gecko_GetSVGAnimatedClass(RawGeckoElementBorrowed aElement) {
 | |
|   MOZ_ASSERT(aElement->IsSVGElement());
 | |
|   return static_cast<const SVGElement*>(aElement)->GetAnimatedClassName();
 | |
| }
 | |
| 
 | |
| bool Gecko_AssertClassAttrValueIsSane(const nsAttrValue* aValue) {
 | |
|   MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom ||
 | |
|              aValue->Type() == nsAttrValue::eString ||
 | |
|              aValue->Type() == nsAttrValue::eAtomArray);
 | |
|   MOZ_ASSERT_IF(
 | |
|       aValue->Type() == nsAttrValue::eString,
 | |
|       nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
 | |
|           aValue->GetStringValue())
 | |
|           .IsEmpty());
 | |
|   return true;
 | |
| }
 |