1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/ServoBindings.h"
8 
9 #include "ChildIterator.h"
10 #include "StyleStructContext.h"
11 #include "gfxFontFamilyList.h"
12 #include "nsAttrValueInlines.h"
13 #include "nsCSSRuleProcessor.h"
14 #include "nsContentUtils.h"
15 #include "nsDOMTokenList.h"
16 #include "nsIContentInlines.h"
17 #include "nsIDOMNode.h"
18 #include "nsIDocument.h"
19 #include "nsIFrame.h"
20 #include "nsINode.h"
21 #include "nsIPrincipal.h"
22 #include "nsNameSpaceManager.h"
23 #include "nsRuleNode.h"
24 #include "nsString.h"
25 #include "nsStyleStruct.h"
26 #include "nsStyleUtil.h"
27 #include "nsTArray.h"
28 
29 #include "mozilla/EventStates.h"
30 #include "mozilla/ServoElementSnapshot.h"
31 #include "mozilla/ServoRestyleManager.h"
32 #include "mozilla/StyleAnimationValue.h"
33 #include "mozilla/DeclarationBlockInlines.h"
34 #include "mozilla/dom/Element.h"
35 
36 using namespace mozilla;
37 using namespace mozilla::dom;
38 
39 #define IMPL_STRONG_REF_TYPE_FOR(type_) \
40   already_AddRefed<type_>               \
41   type_##Strong::Consume() {            \
42     RefPtr<type_> result;               \
43     result.swap(mPtr);                  \
44     return result.forget();             \
45   }
46 
47 IMPL_STRONG_REF_TYPE_FOR(ServoComputedValues)
IMPL_STRONG_REF_TYPE_FOR(RawServoStyleSheet)48 IMPL_STRONG_REF_TYPE_FOR(RawServoStyleSheet)
49 IMPL_STRONG_REF_TYPE_FOR(RawServoDeclarationBlock)
50 
51 #undef IMPL_STRONG_REF_TYPE_FOR
52 
53 uint32_t
54 Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
55 {
56   return aNode->GetChildCount();
57 }
58 
59 bool
Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)60 Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
61 {
62   return aNode->IsElement();
63 }
64 
65 RawGeckoNodeBorrowedOrNull
Gecko_GetParentNode(RawGeckoNodeBorrowed aNode)66 Gecko_GetParentNode(RawGeckoNodeBorrowed aNode)
67 {
68   return aNode->GetFlattenedTreeParentNode();
69 }
70 
71 RawGeckoNodeBorrowedOrNull
Gecko_GetFirstChild(RawGeckoNodeBorrowed aNode)72 Gecko_GetFirstChild(RawGeckoNodeBorrowed aNode)
73 {
74   return aNode->GetFirstChild();
75 }
76 
77 RawGeckoNodeBorrowedOrNull
Gecko_GetLastChild(RawGeckoNodeBorrowed aNode)78 Gecko_GetLastChild(RawGeckoNodeBorrowed aNode)
79 {
80   return aNode->GetLastChild();
81 }
82 
83 RawGeckoNodeBorrowedOrNull
Gecko_GetPrevSibling(RawGeckoNodeBorrowed aNode)84 Gecko_GetPrevSibling(RawGeckoNodeBorrowed aNode)
85 {
86   return aNode->GetPreviousSibling();
87 }
88 
89 RawGeckoNodeBorrowedOrNull
Gecko_GetNextSibling(RawGeckoNodeBorrowed aNode)90 Gecko_GetNextSibling(RawGeckoNodeBorrowed aNode)
91 {
92   return aNode->GetNextSibling();
93 }
94 
95 RawGeckoElementBorrowedOrNull
Gecko_GetParentElement(RawGeckoElementBorrowed aElement)96 Gecko_GetParentElement(RawGeckoElementBorrowed aElement)
97 {
98   nsINode* parentNode = aElement->GetFlattenedTreeParentNode();
99   return parentNode->IsElement() ? parentNode->AsElement() : nullptr;
100 }
101 
102 RawGeckoElementBorrowedOrNull
Gecko_GetFirstChildElement(RawGeckoElementBorrowed aElement)103 Gecko_GetFirstChildElement(RawGeckoElementBorrowed aElement)
104 {
105   return aElement->GetFirstElementChild();
106 }
107 
Gecko_GetLastChildElement(RawGeckoElementBorrowed aElement)108 RawGeckoElementBorrowedOrNull Gecko_GetLastChildElement(RawGeckoElementBorrowed aElement)
109 {
110   return aElement->GetLastElementChild();
111 }
112 
113 RawGeckoElementBorrowedOrNull
Gecko_GetPrevSiblingElement(RawGeckoElementBorrowed aElement)114 Gecko_GetPrevSiblingElement(RawGeckoElementBorrowed aElement)
115 {
116   return aElement->GetPreviousElementSibling();
117 }
118 
119 RawGeckoElementBorrowedOrNull
Gecko_GetNextSiblingElement(RawGeckoElementBorrowed aElement)120 Gecko_GetNextSiblingElement(RawGeckoElementBorrowed aElement)
121 {
122   return aElement->GetNextElementSibling();
123 }
124 
125 RawGeckoElementBorrowedOrNull
Gecko_GetDocumentElement(RawGeckoDocumentBorrowed aDoc)126 Gecko_GetDocumentElement(RawGeckoDocumentBorrowed aDoc)
127 {
128   return aDoc->GetDocumentElement();
129 }
130 
131 StyleChildrenIteratorOwnedOrNull
Gecko_MaybeCreateStyleChildrenIterator(RawGeckoNodeBorrowed aNode)132 Gecko_MaybeCreateStyleChildrenIterator(RawGeckoNodeBorrowed aNode)
133 {
134   if (!aNode->IsElement()) {
135     return nullptr;
136   }
137 
138   const Element* el = aNode->AsElement();
139   return StyleChildrenIterator::IsNeeded(el) ? new StyleChildrenIterator(el)
140                                              : nullptr;
141 }
142 
143 void
Gecko_DropStyleChildrenIterator(StyleChildrenIteratorOwned aIterator)144 Gecko_DropStyleChildrenIterator(StyleChildrenIteratorOwned aIterator)
145 {
146   MOZ_ASSERT(aIterator);
147   delete aIterator;
148 }
149 
150 RawGeckoNodeBorrowed
Gecko_GetNextStyleChild(StyleChildrenIteratorBorrowedMut aIterator)151 Gecko_GetNextStyleChild(StyleChildrenIteratorBorrowedMut aIterator)
152 {
153   MOZ_ASSERT(aIterator);
154   return aIterator->GetNextChild();
155 }
156 
157 EventStates::ServoType
Gecko_ElementState(RawGeckoElementBorrowed aElement)158 Gecko_ElementState(RawGeckoElementBorrowed aElement)
159 {
160   return aElement->StyleState().ServoValue();
161 }
162 
163 bool
Gecko_IsHTMLElementInHTMLDocument(RawGeckoElementBorrowed aElement)164 Gecko_IsHTMLElementInHTMLDocument(RawGeckoElementBorrowed aElement)
165 {
166   return aElement->IsHTMLElement() && aElement->OwnerDoc()->IsHTMLDocument();
167 }
168 
169 bool
Gecko_IsLink(RawGeckoElementBorrowed aElement)170 Gecko_IsLink(RawGeckoElementBorrowed aElement)
171 {
172   return nsCSSRuleProcessor::IsLink(aElement);
173 }
174 
175 bool
Gecko_IsTextNode(RawGeckoNodeBorrowed aNode)176 Gecko_IsTextNode(RawGeckoNodeBorrowed aNode)
177 {
178   return aNode->NodeInfo()->NodeType() == nsIDOMNode::TEXT_NODE;
179 }
180 
181 bool
Gecko_IsVisitedLink(RawGeckoElementBorrowed aElement)182 Gecko_IsVisitedLink(RawGeckoElementBorrowed aElement)
183 {
184   return aElement->StyleState().HasState(NS_EVENT_STATE_VISITED);
185 }
186 
187 bool
Gecko_IsUnvisitedLink(RawGeckoElementBorrowed aElement)188 Gecko_IsUnvisitedLink(RawGeckoElementBorrowed aElement)
189 {
190   return aElement->StyleState().HasState(NS_EVENT_STATE_UNVISITED);
191 }
192 
193 bool
Gecko_IsRootElement(RawGeckoElementBorrowed aElement)194 Gecko_IsRootElement(RawGeckoElementBorrowed aElement)
195 {
196   return aElement->OwnerDoc()->GetRootElement() == aElement;
197 }
198 
199 nsIAtom*
Gecko_LocalName(RawGeckoElementBorrowed aElement)200 Gecko_LocalName(RawGeckoElementBorrowed aElement)
201 {
202   return aElement->NodeInfo()->NameAtom();
203 }
204 
205 nsIAtom*
Gecko_Namespace(RawGeckoElementBorrowed aElement)206 Gecko_Namespace(RawGeckoElementBorrowed aElement)
207 {
208   int32_t id = aElement->NodeInfo()->NamespaceID();
209   return nsContentUtils::NameSpaceManager()->NameSpaceURIAtomForServo(id);
210 }
211 
212 nsIAtom*
Gecko_GetElementId(RawGeckoElementBorrowed aElement)213 Gecko_GetElementId(RawGeckoElementBorrowed aElement)
214 {
215   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::id);
216   return attr ? attr->GetAtomValue() : nullptr;
217 }
218 
219 // Dirtiness tracking.
220 uint32_t
Gecko_GetNodeFlags(RawGeckoNodeBorrowed aNode)221 Gecko_GetNodeFlags(RawGeckoNodeBorrowed aNode)
222 {
223   return aNode->GetFlags();
224 }
225 
226 void
Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode,uint32_t aFlags)227 Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
228 {
229   const_cast<nsINode*>(aNode)->SetFlags(aFlags);
230 }
231 
232 void
Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed aNode,uint32_t aFlags)233 Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
234 {
235   const_cast<nsINode*>(aNode)->UnsetFlags(aFlags);
236 }
237 
238 nsStyleContext*
Gecko_GetStyleContext(RawGeckoNodeBorrowed aNode,nsIAtom * aPseudoTagOrNull)239 Gecko_GetStyleContext(RawGeckoNodeBorrowed aNode, nsIAtom* aPseudoTagOrNull)
240 {
241   MOZ_ASSERT(aNode->IsContent());
242   nsIFrame* relevantFrame =
243     ServoRestyleManager::FrameForPseudoElement(aNode->AsContent(),
244                                                aPseudoTagOrNull);
245   if (!relevantFrame) {
246     return nullptr;
247   }
248 
249   return relevantFrame->StyleContext();
250 }
251 
252 nsChangeHint
Gecko_CalcStyleDifference(nsStyleContext * aOldStyleContext,ServoComputedValuesBorrowed aComputedValues)253 Gecko_CalcStyleDifference(nsStyleContext* aOldStyleContext,
254                           ServoComputedValuesBorrowed aComputedValues)
255 {
256   MOZ_ASSERT(aOldStyleContext);
257   MOZ_ASSERT(aComputedValues);
258 
259   // Pass the safe thing, which causes us to miss a potential optimization. See
260   // bug 1289863.
261   nsChangeHint forDescendants = nsChangeHint_Hints_NotHandledForDescendants;
262 
263   // Eventually, we should compute things out of these flags like
264   // ElementRestyler::RestyleSelf does and pass the result to the caller to
265   // potentially halt traversal. See bug 1289868.
266   uint32_t equalStructs, samePointerStructs;
267   nsChangeHint result =
268     aOldStyleContext->CalcStyleDifference(aComputedValues,
269                                           forDescendants,
270                                           &equalStructs,
271                                           &samePointerStructs);
272 
273   return result;
274 }
275 
276 void
Gecko_StoreStyleDifference(RawGeckoNodeBorrowed aNode,nsChangeHint aChangeHintToStore)277 Gecko_StoreStyleDifference(RawGeckoNodeBorrowed aNode, nsChangeHint aChangeHintToStore)
278 {
279 #ifdef MOZ_STYLO
280   MOZ_ASSERT(aNode->IsElement());
281   MOZ_ASSERT(aNode->IsDirtyForServo(),
282              "Change hint stored in a not-dirty node");
283 
284   const Element* aElement = aNode->AsElement();
285   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
286   if (!primaryFrame) {
287     // If there's no primary frame, that means that either this content is
288     // undisplayed (so we only need to check at the restyling phase for the
289     // display value on the element), or is a display: contents element.
290     //
291     // In this second case, we should store it in the frame constructor display
292     // contents map. Note that while this operation looks hairy, this would be
293     // thread-safe because the content should be there already (we'd only need
294     // to read the map and modify our entry).
295     //
296     // That being said, we still don't support display: contents anyway, so it's
297     // probably not worth it to do all the roundtrip just yet until we have a
298     // more concrete plan.
299     return;
300   }
301 
302   if ((aChangeHintToStore & nsChangeHint_ReconstructFrame) &&
303       aNode->IsInNativeAnonymousSubtree())
304   {
305     NS_WARNING("stylo: Removing forbidden frame reconstruction hint on native "
306                "anonymous content. Fix this in bug 1297857!");
307     aChangeHintToStore &= ~nsChangeHint_ReconstructFrame;
308   }
309 
310   primaryFrame->StyleContext()->StoreChangeHint(aChangeHintToStore);
311 #else
312   MOZ_CRASH("stylo: Shouldn't call Gecko_StoreStyleDifference in "
313             "non-stylo build");
314 #endif
315 }
316 
317 RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)318 Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
319 {
320   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::style);
321   if (!attr || attr->Type() != nsAttrValue::eCSSDeclaration) {
322     return nullptr;
323   }
324   DeclarationBlock* decl = attr->GetCSSDeclarationValue();
325   if (!decl) {
326     return nullptr;
327   }
328   if (decl->IsGecko()) {
329     // XXX This can happen at least when script sets style attribute
330     //     since we haven't implemented Element.style for stylo. But
331     //     we may want to turn it into an assertion after that's done.
332     NS_WARNING("stylo: requesting a Gecko declaration block?");
333     return nullptr;
334   }
335   return reinterpret_cast<const RawServoDeclarationBlockStrong*>
336     (decl->AsServo()->RefRaw());
337 }
338 
339 void
Gecko_FillAllBackgroundLists(nsStyleImageLayers * aLayers,uint32_t aMaxLen)340 Gecko_FillAllBackgroundLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
341 {
342   nsRuleNode::FillAllBackgroundLists(*aLayers, aMaxLen);
343 }
344 
345 void
Gecko_FillAllMaskLists(nsStyleImageLayers * aLayers,uint32_t aMaxLen)346 Gecko_FillAllMaskLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
347 {
348   nsRuleNode::FillAllMaskLists(*aLayers, aMaxLen);
349 }
350 
351 template <typename Implementor>
352 static nsIAtom*
AtomAttrValue(Implementor * aElement,nsIAtom * aName)353 AtomAttrValue(Implementor* aElement, nsIAtom* aName)
354 {
355   const nsAttrValue* attr = aElement->GetParsedAttr(aName);
356   return attr ? attr->GetAtomValue() : nullptr;
357 }
358 
359 template <typename Implementor, typename MatchFn>
360 static bool
DoMatch(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,MatchFn aMatch)361 DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
362 {
363   if (aNS) {
364     int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
365                                                                     aElement->IsInChromeDocument());
366     NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
367     const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
368     return value && aMatch(value);
369   }
370   // No namespace means any namespace - we have to check them all. :-(
371   BorrowedAttrInfo attrInfo;
372   for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
373     if (attrInfo.mName->LocalName() != aName) {
374       continue;
375     }
376     if (aMatch(attrInfo.mValue)) {
377       return true;
378     }
379   }
380   return false;
381 }
382 
383 template <typename Implementor>
384 static bool
HasAttr(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName)385 HasAttr(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName)
386 {
387   auto match = [](const nsAttrValue* aValue) { return true; };
388   return DoMatch(aElement, aNS, aName, match);
389 }
390 
391 template <typename Implementor>
392 static bool
AttrEquals(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr,bool aIgnoreCase)393 AttrEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, nsIAtom* aStr,
394            bool aIgnoreCase)
395 {
396   auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
397     return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
398   };
399   return DoMatch(aElement, aNS, aName, match);
400 }
401 
402 template <typename Implementor>
403 static bool
AttrDashEquals(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr)404 AttrDashEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
405                nsIAtom* aStr)
406 {
407   auto match = [aStr](const nsAttrValue* aValue) {
408     nsAutoString str;
409     aValue->ToString(str);
410     const nsDefaultStringComparator c;
411     return nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c);
412   };
413   return DoMatch(aElement, aNS, aName, match);
414 }
415 
416 template <typename Implementor>
417 static bool
AttrIncludes(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr)418 AttrIncludes(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
419              nsIAtom* aStr)
420 {
421   auto match = [aStr](const nsAttrValue* aValue) {
422     nsAutoString str;
423     aValue->ToString(str);
424     const nsDefaultStringComparator c;
425     return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c);
426   };
427   return DoMatch(aElement, aNS, aName, match);
428 }
429 
430 template <typename Implementor>
431 static bool
AttrHasSubstring(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr)432 AttrHasSubstring(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
433                  nsIAtom* aStr)
434 {
435   auto match = [aStr](const nsAttrValue* aValue) {
436     nsAutoString str;
437     aValue->ToString(str);
438     return FindInReadable(str, nsDependentAtomString(aStr));
439   };
440   return DoMatch(aElement, aNS, aName, match);
441 }
442 
443 template <typename Implementor>
444 static bool
AttrHasPrefix(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr)445 AttrHasPrefix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
446               nsIAtom* aStr)
447 {
448   auto match = [aStr](const nsAttrValue* aValue) {
449     nsAutoString str;
450     aValue->ToString(str);
451     return StringBeginsWith(str, nsDependentAtomString(aStr));
452   };
453   return DoMatch(aElement, aNS, aName, match);
454 }
455 
456 template <typename Implementor>
457 static bool
AttrHasSuffix(Implementor * aElement,nsIAtom * aNS,nsIAtom * aName,nsIAtom * aStr)458 AttrHasSuffix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
459               nsIAtom* aStr)
460 {
461   auto match = [aStr](const nsAttrValue* aValue) {
462     nsAutoString str;
463     aValue->ToString(str);
464     return StringEndsWith(str, nsDependentAtomString(aStr));
465   };
466   return DoMatch(aElement, aNS, aName, match);
467 }
468 
469 /**
470  * Gets the class or class list (if any) of the implementor. The calling
471  * convention here is rather hairy, and is optimized for getting Servo the
472  * information it needs for hot calls.
473  *
474  * The return value indicates the number of classes. If zero, neither outparam
475  * is valid. If one, the class_ outparam is filled with the atom of the class.
476  * If two or more, the classList outparam is set to point to an array of atoms
477  * representing the class list.
478  *
479  * The array is borrowed and the atoms are not addrefed. These values can be
480  * invalidated by any DOM mutation. Use them in a tight scope.
481  */
482 template <typename Implementor>
483 static uint32_t
ClassOrClassList(Implementor * aElement,nsIAtom ** aClass,nsIAtom *** aClassList)484 ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList)
485 {
486   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::_class);
487   if (!attr) {
488     return 0;
489   }
490 
491   // For class values with only whitespace, Gecko just stores a string. For the
492   // purposes of the style system, there is no class in this case.
493   if (attr->Type() == nsAttrValue::eString) {
494     MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
495                  attr->GetStringValue()).IsEmpty());
496     return 0;
497   }
498 
499   // Single tokens are generally stored as an atom. Check that case.
500   if (attr->Type() == nsAttrValue::eAtom) {
501     *aClass = attr->GetAtomValue();
502     return 1;
503   }
504 
505   // At this point we should have an atom array. It is likely, but not
506   // guaranteed, that we have two or more elements in the array.
507   MOZ_ASSERT(attr->Type() == nsAttrValue::eAtomArray);
508   nsTArray<nsCOMPtr<nsIAtom>>* atomArray = attr->GetAtomArrayValue();
509   uint32_t length = atomArray->Length();
510 
511   // Special case: zero elements.
512   if (length == 0) {
513     return 0;
514   }
515 
516   // Special case: one element.
517   if (length == 1) {
518     *aClass = atomArray->ElementAt(0);
519     return 1;
520   }
521 
522   // General case: Two or more elements.
523   //
524   // Note: We could also expose this array as an array of nsCOMPtrs, since
525   // bindgen knows what those look like, and eliminate the reinterpret_cast.
526   // But it's not obvious that that would be preferable.
527   static_assert(sizeof(nsCOMPtr<nsIAtom>) == sizeof(nsIAtom*), "Bad simplification");
528   static_assert(alignof(nsCOMPtr<nsIAtom>) == alignof(nsIAtom*), "Bad simplification");
529 
530   nsCOMPtr<nsIAtom>* elements = atomArray->Elements();
531   nsIAtom** rawElements = reinterpret_cast<nsIAtom**>(elements);
532   *aClassList = rawElements;
533   return atomArray->Length();
534 }
535 
536 #define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_)      \
537   nsIAtom* prefix_##AtomAttrValue(implementor_ aElement, nsIAtom* aName)       \
538   {                                                                            \
539     return AtomAttrValue(aElement, aName);                                     \
540   }                                                                            \
541   bool prefix_##HasAttr(implementor_ aElement, nsIAtom* aNS, nsIAtom* aName)   \
542   {                                                                            \
543     return HasAttr(aElement, aNS, aName);                                      \
544   }                                                                            \
545   bool prefix_##AttrEquals(implementor_ aElement, nsIAtom* aNS,                \
546                            nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase)    \
547   {                                                                            \
548     return AttrEquals(aElement, aNS, aName, aStr, aIgnoreCase);                \
549   }                                                                            \
550   bool prefix_##AttrDashEquals(implementor_ aElement, nsIAtom* aNS,            \
551                                nsIAtom* aName, nsIAtom* aStr)                  \
552   {                                                                            \
553     return AttrDashEquals(aElement, aNS, aName, aStr);                         \
554   }                                                                            \
555   bool prefix_##AttrIncludes(implementor_ aElement, nsIAtom* aNS,              \
556                              nsIAtom* aName, nsIAtom* aStr)                    \
557   {                                                                            \
558     return AttrIncludes(aElement, aNS, aName, aStr);                           \
559   }                                                                            \
560   bool prefix_##AttrHasSubstring(implementor_ aElement, nsIAtom* aNS,          \
561                                  nsIAtom* aName, nsIAtom* aStr)                \
562   {                                                                            \
563     return AttrHasSubstring(aElement, aNS, aName, aStr);                       \
564   }                                                                            \
565   bool prefix_##AttrHasPrefix(implementor_ aElement, nsIAtom* aNS,             \
566                               nsIAtom* aName, nsIAtom* aStr)                   \
567   {                                                                            \
568     return AttrHasPrefix(aElement, aNS, aName, aStr);                          \
569   }                                                                            \
570   bool prefix_##AttrHasSuffix(implementor_ aElement, nsIAtom* aNS,             \
571                               nsIAtom* aName, nsIAtom* aStr)                   \
572   {                                                                            \
573     return AttrHasSuffix(aElement, aNS, aName, aStr);                          \
574   }                                                                            \
575   uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsIAtom** aClass,  \
576                                      nsIAtom*** aClassList)                    \
577   {                                                                            \
578     return ClassOrClassList(aElement, aClass, aClassList);                     \
579   }
580 
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_,RawGeckoElementBorrowed)581 SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
582 SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, ServoElementSnapshot*)
583 
584 #undef SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS
585 
586 nsIAtom*
587 Gecko_Atomize(const char* aString, uint32_t aLength)
588 {
589   return NS_Atomize(nsDependentCSubstring(aString, aLength)).take();
590 }
591 
592 void
Gecko_AddRefAtom(nsIAtom * aAtom)593 Gecko_AddRefAtom(nsIAtom* aAtom)
594 {
595   NS_ADDREF(aAtom);
596 }
597 
598 void
Gecko_ReleaseAtom(nsIAtom * aAtom)599 Gecko_ReleaseAtom(nsIAtom* aAtom)
600 {
601   NS_RELEASE(aAtom);
602 }
603 
604 const uint16_t*
Gecko_GetAtomAsUTF16(nsIAtom * aAtom,uint32_t * aLength)605 Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength)
606 {
607   static_assert(sizeof(char16_t) == sizeof(uint16_t), "Servo doesn't know what a char16_t is");
608   MOZ_ASSERT(aAtom);
609   *aLength = aAtom->GetLength();
610 
611   // We need to manually cast from char16ptr_t to const char16_t* to handle the
612   // MOZ_USE_CHAR16_WRAPPER we use on WIndows.
613   return reinterpret_cast<const uint16_t*>(static_cast<const char16_t*>(aAtom->GetUTF16String()));
614 }
615 
616 bool
Gecko_AtomEqualsUTF8(nsIAtom * aAtom,const char * aString,uint32_t aLength)617 Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength)
618 {
619   // XXXbholley: We should be able to do this without converting, I just can't
620   // find the right thing to call.
621   nsDependentAtomString atomStr(aAtom);
622   NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
623   return atomStr.Equals(inStr);
624 }
625 
626 bool
Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom * aAtom,const char * aString,uint32_t aLength)627 Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength)
628 {
629   // XXXbholley: We should be able to do this without converting, I just can't
630   // find the right thing to call.
631   nsDependentAtomString atomStr(aAtom);
632   NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
633   return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr);
634 }
635 
636 void
Gecko_Utf8SliceToString(nsString * aString,const uint8_t * aBuffer,size_t aBufferLen)637 Gecko_Utf8SliceToString(nsString* aString,
638                         const uint8_t* aBuffer,
639                         size_t aBufferLen)
640 {
641   MOZ_ASSERT(aString);
642   MOZ_ASSERT(aBuffer);
643 
644   aString->Truncate();
645   AppendUTF8toUTF16(Substring(reinterpret_cast<const char*>(aBuffer),
646                               aBufferLen), *aString);
647 }
648 
649 void
Gecko_FontFamilyList_Clear(FontFamilyList * aList)650 Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
651   aList->Clear();
652 }
653 
654 void
Gecko_FontFamilyList_AppendNamed(FontFamilyList * aList,nsIAtom * aName)655 Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName)
656 {
657   // Servo doesn't record whether the name was quoted or unquoted, so just
658   // assume unquoted for now.
659   FontFamilyName family;
660   aName->ToString(family.mName);
661   aList->Append(family);
662 }
663 
664 void
Gecko_FontFamilyList_AppendGeneric(FontFamilyList * aList,FontFamilyType aType)665 Gecko_FontFamilyList_AppendGeneric(FontFamilyList* aList, FontFamilyType aType)
666 {
667   aList->Append(FontFamilyName(aType));
668 }
669 
670 void
Gecko_CopyFontFamilyFrom(nsFont * dst,const nsFont * src)671 Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src)
672 {
673   dst->fontlist = src->fontlist;
674 }
675 
676 void
Gecko_SetListStyleType(nsStyleList * style_struct,uint32_t type)677 Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type)
678 {
679   // Builtin counter styles are static and use no-op refcounting, and thus are
680   // safe to use off-main-thread.
681   style_struct->SetCounterStyle(CounterStyleManager::GetBuiltinStyle(type));
682 }
683 
684 void
Gecko_CopyListStyleTypeFrom(nsStyleList * dst,const nsStyleList * src)685 Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src)
686 {
687   dst->SetCounterStyle(src->GetCounterStyle());
688 }
689 
NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIPrincipal,Principal)690 NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
691 NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
692 
693 void
694 Gecko_SetMozBinding(nsStyleDisplay* aDisplay,
695                     const uint8_t* aURLString, uint32_t aURLStringLength,
696                     ThreadSafeURIHolder* aBaseURI,
697                     ThreadSafeURIHolder* aReferrer,
698                     ThreadSafePrincipalHolder* aPrincipal)
699 {
700   MOZ_ASSERT(aDisplay);
701   MOZ_ASSERT(aURLString);
702   MOZ_ASSERT(aBaseURI);
703   MOZ_ASSERT(aReferrer);
704   MOZ_ASSERT(aPrincipal);
705 
706   nsString url;
707   nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURLString),
708                                   aURLStringLength);
709   AppendUTF8toUTF16(urlString, url);
710   RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
711 
712   aDisplay->mBinding =
713     new css::URLValue(urlBuffer, do_AddRef(aBaseURI),
714                       do_AddRef(aReferrer), do_AddRef(aPrincipal));
715 }
716 
717 void
Gecko_CopyMozBindingFrom(nsStyleDisplay * aDest,const nsStyleDisplay * aSrc)718 Gecko_CopyMozBindingFrom(nsStyleDisplay* aDest, const nsStyleDisplay* aSrc)
719 {
720   aDest->mBinding = aSrc->mBinding;
721 }
722 
723 
724 void
Gecko_SetNullImageValue(nsStyleImage * aImage)725 Gecko_SetNullImageValue(nsStyleImage* aImage)
726 {
727   MOZ_ASSERT(aImage);
728   aImage->SetNull();
729 }
730 
731 void
Gecko_SetGradientImageValue(nsStyleImage * aImage,nsStyleGradient * aGradient)732 Gecko_SetGradientImageValue(nsStyleImage* aImage, nsStyleGradient* aGradient)
733 {
734   MOZ_ASSERT(aImage);
735   aImage->SetGradientData(aGradient);
736 }
737 
738 static already_AddRefed<nsStyleImageRequest>
CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,const uint8_t * aURLString,uint32_t aURLStringLength,ThreadSafeURIHolder * aBaseURI,ThreadSafeURIHolder * aReferrer,ThreadSafePrincipalHolder * aPrincipal)739 CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,
740                         const uint8_t* aURLString, uint32_t aURLStringLength,
741                         ThreadSafeURIHolder* aBaseURI,
742                         ThreadSafeURIHolder* aReferrer,
743                         ThreadSafePrincipalHolder* aPrincipal)
744 {
745   MOZ_ASSERT(aURLString);
746   MOZ_ASSERT(aBaseURI);
747   MOZ_ASSERT(aReferrer);
748   MOZ_ASSERT(aPrincipal);
749 
750   nsString url;
751   nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURLString),
752                                   aURLStringLength);
753   AppendUTF8toUTF16(urlString, url);
754   RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
755 
756   RefPtr<nsStyleImageRequest> req =
757     new nsStyleImageRequest(aModeFlags, urlBuffer, do_AddRef(aBaseURI),
758                             do_AddRef(aReferrer), do_AddRef(aPrincipal));
759   return req.forget();
760 }
761 
762 void
Gecko_SetUrlImageValue(nsStyleImage * aImage,const uint8_t * aURLString,uint32_t aURLStringLength,ThreadSafeURIHolder * aBaseURI,ThreadSafeURIHolder * aReferrer,ThreadSafePrincipalHolder * aPrincipal)763 Gecko_SetUrlImageValue(nsStyleImage* aImage,
764                        const uint8_t* aURLString, uint32_t aURLStringLength,
765                        ThreadSafeURIHolder* aBaseURI,
766                        ThreadSafeURIHolder* aReferrer,
767                        ThreadSafePrincipalHolder* aPrincipal)
768 {
769   RefPtr<nsStyleImageRequest> req =
770     CreateStyleImageRequest(nsStyleImageRequest::Mode::Track,
771                             aURLString, aURLStringLength,
772                             aBaseURI, aReferrer, aPrincipal);
773   aImage->SetImageRequest(req.forget());
774 }
775 
776 void
Gecko_CopyImageValueFrom(nsStyleImage * aImage,const nsStyleImage * aOther)777 Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
778 {
779   MOZ_ASSERT(aImage);
780   MOZ_ASSERT(aOther);
781 
782   *aImage = *aOther;
783 }
784 
785 nsStyleGradient*
Gecko_CreateGradient(uint8_t aShape,uint8_t aSize,bool aRepeating,bool aLegacySyntax,uint32_t aStopCount)786 Gecko_CreateGradient(uint8_t aShape,
787                      uint8_t aSize,
788                      bool aRepeating,
789                      bool aLegacySyntax,
790                      uint32_t aStopCount)
791 {
792   nsStyleGradient* result = new nsStyleGradient();
793 
794   result->mShape = aShape;
795   result->mSize = aSize;
796   result->mRepeating = aRepeating;
797   result->mLegacySyntax = aLegacySyntax;
798 
799   result->mAngle.SetNoneValue();
800   result->mBgPosX.SetNoneValue();
801   result->mBgPosY.SetNoneValue();
802   result->mRadiusX.SetNoneValue();
803   result->mRadiusY.SetNoneValue();
804 
805   nsStyleGradientStop dummyStop;
806   dummyStop.mLocation.SetNoneValue();
807   dummyStop.mColor = NS_RGB(0, 0, 0);
808   dummyStop.mIsInterpolationHint = 0;
809 
810   for (uint32_t i = 0; i < aStopCount; i++) {
811     result->mStops.AppendElement(dummyStop);
812   }
813 
814   return result;
815 }
816 
817 void
Gecko_SetListStyleImageNone(nsStyleList * aList)818 Gecko_SetListStyleImageNone(nsStyleList* aList)
819 {
820   aList->mListStyleImage = nullptr;
821 }
822 
823 void
Gecko_SetListStyleImage(nsStyleList * aList,const uint8_t * aURLString,uint32_t aURLStringLength,ThreadSafeURIHolder * aBaseURI,ThreadSafeURIHolder * aReferrer,ThreadSafePrincipalHolder * aPrincipal)824 Gecko_SetListStyleImage(nsStyleList* aList,
825                         const uint8_t* aURLString, uint32_t aURLStringLength,
826                         ThreadSafeURIHolder* aBaseURI,
827                         ThreadSafeURIHolder* aReferrer,
828                         ThreadSafePrincipalHolder* aPrincipal)
829 {
830   aList->mListStyleImage =
831     CreateStyleImageRequest(nsStyleImageRequest::Mode(0),
832                             aURLString, aURLStringLength,
833                             aBaseURI, aReferrer, aPrincipal);
834 }
835 
836 void
Gecko_CopyListStyleImageFrom(nsStyleList * aList,const nsStyleList * aSource)837 Gecko_CopyListStyleImageFrom(nsStyleList* aList, const nsStyleList* aSource)
838 {
839   aList->mListStyleImage = aSource->mListStyleImage;
840 }
841 
842 void
Gecko_EnsureTArrayCapacity(void * aArray,size_t aCapacity,size_t aElemSize)843 Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity, size_t aElemSize)
844 {
845   auto base =
846     reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
847                                    nsTArray_CopyWithMemutils>*>(aArray);
848 
849   base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
850 }
851 
852 void
Gecko_ClearPODTArray(void * aArray,size_t aElementSize,size_t aElementAlign)853 Gecko_ClearPODTArray(void* aArray, size_t aElementSize, size_t aElementAlign)
854 {
855   auto base =
856     reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
857                                    nsTArray_CopyWithMemutils>*>(aArray);
858 
859   base->template ShiftData<nsTArrayInfallibleAllocator>(0, base->Length(), 0,
860                                                         aElementSize, aElementAlign);
861 }
862 
863 void
Gecko_ClearStyleContents(nsStyleContent * aContent)864 Gecko_ClearStyleContents(nsStyleContent* aContent)
865 {
866   aContent->AllocateContents(0);
867 }
868 
869 void
Gecko_CopyStyleContentsFrom(nsStyleContent * aContent,const nsStyleContent * aOther)870 Gecko_CopyStyleContentsFrom(nsStyleContent* aContent, const nsStyleContent* aOther)
871 {
872   uint32_t count = aOther->ContentCount();
873 
874   aContent->AllocateContents(count);
875 
876   for (uint32_t i = 0; i < count; ++i) {
877     aContent->ContentAt(i) = aOther->ContentAt(i);
878   }
879 }
880 
881 void
Gecko_EnsureImageLayersLength(nsStyleImageLayers * aLayers,size_t aLen,nsStyleImageLayers::LayerType aLayerType)882 Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
883                               nsStyleImageLayers::LayerType aLayerType)
884 {
885   size_t oldLength = aLayers->mLayers.Length();
886 
887   aLayers->mLayers.EnsureLengthAtLeast(aLen);
888 
889   for (size_t i = oldLength; i < aLen; ++i) {
890     aLayers->mLayers[i].Initialize(aLayerType);
891   }
892 }
893 
894 void
Gecko_ResetStyleCoord(nsStyleUnit * aUnit,nsStyleUnion * aValue)895 Gecko_ResetStyleCoord(nsStyleUnit* aUnit, nsStyleUnion* aValue)
896 {
897   nsStyleCoord::Reset(*aUnit, *aValue);
898 }
899 
900 void
Gecko_SetStyleCoordCalcValue(nsStyleUnit * aUnit,nsStyleUnion * aValue,nsStyleCoord::CalcValue aCalc)901 Gecko_SetStyleCoordCalcValue(nsStyleUnit* aUnit, nsStyleUnion* aValue, nsStyleCoord::CalcValue aCalc)
902 {
903   // Calc units should be cleaned up first
904   MOZ_ASSERT(*aUnit != nsStyleUnit::eStyleUnit_Calc);
905   nsStyleCoord::Calc* calcRef = new nsStyleCoord::Calc();
906   calcRef->mLength = aCalc.mLength;
907   calcRef->mPercent = aCalc.mPercent;
908   calcRef->mHasPercent = aCalc.mHasPercent;
909   *aUnit = nsStyleUnit::eStyleUnit_Calc;
910   aValue->mPointer = calcRef;
911   calcRef->AddRef();
912 }
913 
914 void
Gecko_CopyClipPathValueFrom(mozilla::StyleClipPath * aDst,const mozilla::StyleClipPath * aSrc)915 Gecko_CopyClipPathValueFrom(mozilla::StyleClipPath* aDst, const mozilla::StyleClipPath* aSrc)
916 {
917   MOZ_ASSERT(aDst);
918   MOZ_ASSERT(aSrc);
919 
920   *aDst = *aSrc;
921 }
922 
923 void
Gecko_DestroyClipPath(mozilla::StyleClipPath * aClip)924 Gecko_DestroyClipPath(mozilla::StyleClipPath* aClip)
925 {
926   aClip->~StyleClipPath();
927 }
928 
929 mozilla::StyleBasicShape*
Gecko_NewBasicShape(mozilla::StyleBasicShapeType aType)930 Gecko_NewBasicShape(mozilla::StyleBasicShapeType aType)
931 {
932   RefPtr<StyleBasicShape> ptr = new mozilla::StyleBasicShape(aType);
933   return ptr.forget().take();
934 }
935 
936 void
Gecko_ResetFilters(nsStyleEffects * effects,size_t new_len)937 Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len)
938 {
939   effects->mFilters.Clear();
940   effects->mFilters.SetLength(new_len);
941 }
942 
943 void
Gecko_CopyFiltersFrom(nsStyleEffects * aSrc,nsStyleEffects * aDest)944 Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest)
945 {
946   aDest->mFilters = aSrc->mFilters;
947 }
948 
949 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
950 
951 nsCSSShadowArray*
Gecko_NewCSSShadowArray(uint32_t aLen)952 Gecko_NewCSSShadowArray(uint32_t aLen)
953 {
954   RefPtr<nsCSSShadowArray> arr = new(aLen) nsCSSShadowArray(aLen);
955   return arr.forget().take();
956 }
957 
958 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
959 
960 nsStyleQuoteValues*
Gecko_NewStyleQuoteValues(uint32_t aLen)961 Gecko_NewStyleQuoteValues(uint32_t aLen)
962 {
963   RefPtr<nsStyleQuoteValues> values = new nsStyleQuoteValues;
964   values->mQuotePairs.SetLength(aLen);
965   return values.forget().take();
966 }
967 
968 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues);
969 
970 nsCSSValueSharedList*
Gecko_NewCSSValueSharedList(uint32_t aLen)971 Gecko_NewCSSValueSharedList(uint32_t aLen)
972 {
973   RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
974   if (aLen == 0) {
975     return list.forget().take();
976   }
977 
978   list->mHead = new nsCSSValueList;
979   nsCSSValueList* cur = list->mHead;
980   for (uint32_t i = 0; i < aLen - 1; i++) {
981     cur->mNext = new nsCSSValueList;
982     cur = cur->mNext;
983   }
984 
985   return list.forget().take();
986 }
987 
988 void
Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut aCSSValue,nscoord aLen)989 Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut aCSSValue, nscoord aLen)
990 {
991   aCSSValue->SetIntegerCoordValue(aLen);
992 }
993 
994 void
Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue,float aNumber)995 Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue, float aNumber)
996 {
997   aCSSValue->SetFloatValue(aNumber, eCSSUnit_Number);
998 }
999 
1000 void
Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue,nsCSSKeyword aKeyword)1001 Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue, nsCSSKeyword aKeyword)
1002 {
1003   aCSSValue->SetIntValue(aKeyword, eCSSUnit_Enumerated);
1004 }
1005 
1006 void
Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue,float aPercent)1007 Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue, float aPercent)
1008 {
1009   aCSSValue->SetFloatValue(aPercent, eCSSUnit_Number);
1010 }
1011 
1012 void
Gecko_CSSValue_SetAngle(nsCSSValueBorrowedMut aCSSValue,float aRadians)1013 Gecko_CSSValue_SetAngle(nsCSSValueBorrowedMut aCSSValue, float aRadians)
1014 {
1015   aCSSValue->SetFloatValue(aRadians, eCSSUnit_Radian);
1016 }
1017 
1018 void
Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue,nsStyleCoord::CalcValue aCalc)1019 Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue, nsStyleCoord::CalcValue aCalc)
1020 {
1021   aCSSValue->SetCalcValue(&aCalc);
1022 }
1023 
1024 void
Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue,int32_t aLen)1025 Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue, int32_t aLen)
1026 {
1027   nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen);
1028   aCSSValue->SetArrayValue(arr, eCSSUnit_Function);
1029 }
1030 
1031 nsCSSValueBorrowedMut
Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut aCSSValue,int32_t aIndex)1032 Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut aCSSValue, int32_t aIndex)
1033 {
1034   return &aCSSValue->GetArrayValue()->Item(aIndex);
1035 }
1036 
1037 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
1038 
1039 #define STYLE_STRUCT(name, checkdata_cb)                                      \
1040                                                                               \
1041 void                                                                          \
1042 Gecko_Construct_nsStyle##name(nsStyle##name* ptr)                             \
1043 {                                                                             \
1044   new (ptr) nsStyle##name(StyleStructContext::ServoContext());                \
1045 }                                                                             \
1046                                                                               \
1047 void                                                                          \
1048 Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr,                         \
1049                                   const nsStyle##name* other)                 \
1050 {                                                                             \
1051   new (ptr) nsStyle##name(*other);                                            \
1052 }                                                                             \
1053                                                                               \
1054 void                                                                          \
1055 Gecko_Destroy_nsStyle##name(nsStyle##name* ptr)                               \
1056 {                                                                             \
1057   ptr->~nsStyle##name();                                                      \
1058 }
1059 
1060 #include "nsStyleStructList.h"
1061 
1062 #undef STYLE_STRUCT
1063 
1064 #ifndef MOZ_STYLO
1065 #define SERVO_BINDING_FUNC(name_, return_, ...)                               \
1066   return_ name_(__VA_ARGS__) {                                                \
1067     MOZ_CRASH("stylo: shouldn't be calling " #name_ "in a non-stylo build");  \
1068   }
1069 #include "ServoBindingList.h"
1070 #undef SERVO_BINDING_FUNC
1071 #endif
1072 
1073 #ifdef MOZ_STYLO
1074 const nsStyleVariables*
Servo_GetStyleVariables(ServoComputedValuesBorrowed aComputedValues)1075 Servo_GetStyleVariables(ServoComputedValuesBorrowed aComputedValues)
1076 {
1077   // Servo can't provide us with Variables structs yet, so instead of linking
1078   // to a Servo_GetStyleVariables defined in Servo we define one here that
1079   // always returns the same, empty struct.
1080   static nsStyleVariables variables(StyleStructContext::ServoContext());
1081   return &variables;
1082 }
1083 #endif
1084