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