--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -44,24 +44,212 @@ using namespace mozilla::dom;
IMPL_STRONG_REF_TYPE_FOR(ServoComputedValues)
IMPL_STRONG_REF_TYPE_FOR(RawServoStyleSheet)
IMPL_STRONG_REF_TYPE_FOR(ServoDeclarationBlock)
#undef IMPL_STRONG_REF_TYPE_FOR
/**
- * NB: Declared in dom/base/nsINode.h, not to be implemented from Servo.
+ * NB: Declared in dom/base/nsINode.h, not to be implemented from Servo, and
+ * **not an extern "C" function**.
*/
void
Servo_NodeData_DefaultDelete(ServoNodeData* aServoNodeData)
{
Servo_NodeData_Drop(aServoNodeData);
}
+template <typename Implementor>
+static nsIAtom*
+AtomAttrValue(Implementor* aElement, nsIAtom* aName)
+{
+ const nsAttrValue* attr = aElement->GetParsedAttr(aName);
+ return attr ? attr->GetAtomValue() : nullptr;
+}
+
+template <typename Implementor, typename MatchFn>
+static bool
+DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
+{
+ if (aNS) {
+ int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
+ aElement->IsInChromeDocument());
+ NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
+ const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
+ return value && aMatch(value);
+ }
+ // No namespace means any namespace - we have to check them all. :-(
+ BorrowedAttrInfo attrInfo;
+ for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
+ if (attrInfo.mName->LocalName() != aName) {
+ continue;
+ }
+ if (aMatch(attrInfo.mValue)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename Implementor>
+static bool
+HasAttr(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName)
+{
+ auto match = [](const nsAttrValue* aValue) { return true; };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, nsIAtom* aStr,
+ bool aIgnoreCase)
+{
+ auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
+ return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrDashEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
+ nsIAtom* aStr)
+{
+ auto match = [aStr](const nsAttrValue* aValue) {
+ nsAutoString str;
+ aValue->ToString(str);
+ const nsDefaultStringComparator c;
+ return nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c);
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrIncludes(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
+ nsIAtom* aStr)
+{
+ auto match = [aStr](const nsAttrValue* aValue) {
+ nsAutoString str;
+ aValue->ToString(str);
+ const nsDefaultStringComparator c;
+ return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c);
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrHasSubstring(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
+ nsIAtom* aStr)
+{
+ auto match = [aStr](const nsAttrValue* aValue) {
+ nsAutoString str;
+ aValue->ToString(str);
+ return FindInReadable(str, nsDependentAtomString(aStr));
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrHasPrefix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
+ nsIAtom* aStr)
+{
+ auto match = [aStr](const nsAttrValue* aValue) {
+ nsAutoString str;
+ aValue->ToString(str);
+ return StringBeginsWith(str, nsDependentAtomString(aStr));
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+template <typename Implementor>
+static bool
+AttrHasSuffix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
+ nsIAtom* aStr)
+{
+ auto match = [aStr](const nsAttrValue* aValue) {
+ nsAutoString str;
+ aValue->ToString(str);
+ return StringEndsWith(str, nsDependentAtomString(aStr));
+ };
+ return DoMatch(aElement, aNS, aName, match);
+}
+
+/**
+ * Gets the class or class list (if any) of the implementor. The calling
+ * convention here is rather hairy, and is optimized for getting Servo the
+ * information it needs for hot calls.
+ *
+ * The return value indicates the number of classes. If zero, neither outparam
+ * is valid. If one, the class_ outparam is filled with the atom of the class.
+ * If two or more, the classList outparam is set to point to an array of atoms
+ * representing the class list.
+ *
+ * The array is borrowed and the atoms are not addrefed. These values can be
+ * invalidated by any DOM mutation. Use them in a tight scope.
+ */
+template <typename Implementor>
+static uint32_t
+ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList)
+{
+ const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::_class);
+ if (!attr) {
+ return 0;
+ }
+
+ // For class values with only whitespace, Gecko just stores a string. For the
+ // purposes of the style system, there is no class in this case.
+ if (attr->Type() == nsAttrValue::eString) {
+ MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ attr->GetStringValue()).IsEmpty());
+ return 0;
+ }
+
+ // Single tokens are generally stored as an atom. Check that case.
+ if (attr->Type() == nsAttrValue::eAtom) {
+ *aClass = attr->GetAtomValue();
+ return 1;
+ }
+
+ // At this point we should have an atom array. It is likely, but not
+ // guaranteed, that we have two or more elements in the array.
+ MOZ_ASSERT(attr->Type() == nsAttrValue::eAtomArray);
+ nsTArray<nsCOMPtr<nsIAtom>>* atomArray = attr->GetAtomArrayValue();
+ uint32_t length = atomArray->Length();
+
+ // Special case: zero elements.
+ if (length == 0) {
+ return 0;
+ }
+
+ // Special case: one element.
+ if (length == 1) {
+ *aClass = atomArray->ElementAt(0);
+ return 1;
+ }
+
+ // General case: Two or more elements.
+ //
+ // Note: We could also expose this array as an array of nsCOMPtrs, since
+ // bindgen knows what those look like, and eliminate the reinterpret_cast.
+ // But it's not obvious that that would be preferable.
+ static_assert(sizeof(nsCOMPtr<nsIAtom>) == sizeof(nsIAtom*), "Bad simplification");
+ static_assert(alignof(nsCOMPtr<nsIAtom>) == alignof(nsIAtom*), "Bad simplification");
+
+ nsCOMPtr<nsIAtom>* elements = atomArray->Elements();
+ nsIAtom** rawElements = reinterpret_cast<nsIAtom**>(elements);
+ *aClassList = rawElements;
+ return atomArray->Length();
+}
+
+extern "C" {
+
uint32_t
Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
{
return aNode->GetChildCount();
}
bool
Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
@@ -338,201 +526,16 @@ Gecko_FillAllBackgroundLists(nsStyleImag
}
void
Gecko_FillAllMaskLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
{
nsRuleNode::FillAllMaskLists(*aLayers, aMaxLen);
}
-template <typename Implementor>
-static nsIAtom*
-AtomAttrValue(Implementor* aElement, nsIAtom* aName)
-{
- const nsAttrValue* attr = aElement->GetParsedAttr(aName);
- return attr ? attr->GetAtomValue() : nullptr;
-}
-
-template <typename Implementor, typename MatchFn>
-static bool
-DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
-{
- if (aNS) {
- int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
- aElement->IsInChromeDocument());
- NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
- const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
- return value && aMatch(value);
- }
- // No namespace means any namespace - we have to check them all. :-(
- BorrowedAttrInfo attrInfo;
- for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
- if (attrInfo.mName->LocalName() != aName) {
- continue;
- }
- if (aMatch(attrInfo.mValue)) {
- return true;
- }
- }
- return false;
-}
-
-template <typename Implementor>
-static bool
-HasAttr(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName)
-{
- auto match = [](const nsAttrValue* aValue) { return true; };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, nsIAtom* aStr,
- bool aIgnoreCase)
-{
- auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
- return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrDashEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
- nsIAtom* aStr)
-{
- auto match = [aStr](const nsAttrValue* aValue) {
- nsAutoString str;
- aValue->ToString(str);
- const nsDefaultStringComparator c;
- return nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c);
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrIncludes(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
- nsIAtom* aStr)
-{
- auto match = [aStr](const nsAttrValue* aValue) {
- nsAutoString str;
- aValue->ToString(str);
- const nsDefaultStringComparator c;
- return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c);
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrHasSubstring(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
- nsIAtom* aStr)
-{
- auto match = [aStr](const nsAttrValue* aValue) {
- nsAutoString str;
- aValue->ToString(str);
- return FindInReadable(str, nsDependentAtomString(aStr));
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrHasPrefix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
- nsIAtom* aStr)
-{
- auto match = [aStr](const nsAttrValue* aValue) {
- nsAutoString str;
- aValue->ToString(str);
- return StringBeginsWith(str, nsDependentAtomString(aStr));
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-template <typename Implementor>
-static bool
-AttrHasSuffix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
- nsIAtom* aStr)
-{
- auto match = [aStr](const nsAttrValue* aValue) {
- nsAutoString str;
- aValue->ToString(str);
- return StringEndsWith(str, nsDependentAtomString(aStr));
- };
- return DoMatch(aElement, aNS, aName, match);
-}
-
-/**
- * Gets the class or class list (if any) of the implementor. The calling
- * convention here is rather hairy, and is optimized for getting Servo the
- * information it needs for hot calls.
- *
- * The return value indicates the number of classes. If zero, neither outparam
- * is valid. If one, the class_ outparam is filled with the atom of the class.
- * If two or more, the classList outparam is set to point to an array of atoms
- * representing the class list.
- *
- * The array is borrowed and the atoms are not addrefed. These values can be
- * invalidated by any DOM mutation. Use them in a tight scope.
- */
-template <typename Implementor>
-static uint32_t
-ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList)
-{
- const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::_class);
- if (!attr) {
- return 0;
- }
-
- // For class values with only whitespace, Gecko just stores a string. For the
- // purposes of the style system, there is no class in this case.
- if (attr->Type() == nsAttrValue::eString) {
- MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
- attr->GetStringValue()).IsEmpty());
- return 0;
- }
-
- // Single tokens are generally stored as an atom. Check that case.
- if (attr->Type() == nsAttrValue::eAtom) {
- *aClass = attr->GetAtomValue();
- return 1;
- }
-
- // At this point we should have an atom array. It is likely, but not
- // guaranteed, that we have two or more elements in the array.
- MOZ_ASSERT(attr->Type() == nsAttrValue::eAtomArray);
- nsTArray<nsCOMPtr<nsIAtom>>* atomArray = attr->GetAtomArrayValue();
- uint32_t length = atomArray->Length();
-
- // Special case: zero elements.
- if (length == 0) {
- return 0;
- }
-
- // Special case: one element.
- if (length == 1) {
- *aClass = atomArray->ElementAt(0);
- return 1;
- }
-
- // General case: Two or more elements.
- //
- // Note: We could also expose this array as an array of nsCOMPtrs, since
- // bindgen knows what those look like, and eliminate the reinterpret_cast.
- // But it's not obvious that that would be preferable.
- static_assert(sizeof(nsCOMPtr<nsIAtom>) == sizeof(nsIAtom*), "Bad simplification");
- static_assert(alignof(nsCOMPtr<nsIAtom>) == alignof(nsIAtom*), "Bad simplification");
-
- nsCOMPtr<nsIAtom>* elements = atomArray->Elements();
- nsIAtom** rawElements = reinterpret_cast<nsIAtom**>(elements);
- *aClassList = rawElements;
- return atomArray->Length();
-}
-
#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
nsIAtom* prefix_##AtomAttrValue(implementor_ aElement, nsIAtom* aName) \
{ \
return AtomAttrValue(aElement, aName); \
} \
bool prefix_##HasAttr(implementor_ aElement, nsIAtom* aNS, nsIAtom* aName) \
{ \
return HasAttr(aElement, aNS, aName); \
@@ -918,8 +921,10 @@ Servo_GetStyleVariables(ServoComputedVal
{
// Servo can't provide us with Variables structs yet, so instead of linking
// to a Servo_GetStyleVariables defined in Servo we define one here that
// always returns the same, empty struct.
static nsStyleVariables variables(StyleStructContext::ServoContext());
return &variables;
}
#endif
+
+} // extern "C"