ServoBindings.cpp 33 KB

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