mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 14:57:32 +09:00
Implement class selector fast path and add related tests for performance optimization
This commit is contained in:
parent
dfe7760702
commit
80cfaf0891
8 changed files with 233 additions and 2 deletions
|
|
@ -2927,6 +2927,35 @@ FindMatchingElementsWithId(const nsAString& aId, nsINode* aRoot,
|
|||
// Actually find elements matching aSelectorList (which must not be
|
||||
// null) and which are descendants of aRoot and put them in aList. If
|
||||
// onlyFirstMatch, then stop once the first one is found.
|
||||
template<bool onlyFirstMatch, class Collector, class T>
|
||||
static void
|
||||
FindMatchingElementsWithClass(nsINode* aRoot, nsIAtom* aClass,
|
||||
nsCaseTreatment aCaseTreatment, T& aList)
|
||||
{
|
||||
Collector results;
|
||||
for (nsIContent* cur = aRoot->GetFirstChild(); cur;
|
||||
cur = cur->GetNextNode(aRoot)) {
|
||||
if (!cur->IsElement()) {
|
||||
continue;
|
||||
}
|
||||
const nsAttrValue* classes = cur->AsElement()->GetClasses();
|
||||
if (classes && classes->Contains(aClass, aCaseTreatment)) {
|
||||
if (onlyFirstMatch) {
|
||||
aList.AppendElement(cur->AsElement());
|
||||
return;
|
||||
}
|
||||
results.AppendElement(cur->AsElement());
|
||||
}
|
||||
}
|
||||
const uint32_t len = results.Length();
|
||||
if (len) {
|
||||
aList.SetCapacity(len);
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
aList.AppendElement(results.ElementAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<bool onlyFirstMatch, class Collector, class T>
|
||||
MOZ_ALWAYS_INLINE static void
|
||||
FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
|
||||
|
|
@ -2934,6 +2963,23 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
|
|||
{
|
||||
nsIDocument* doc = aRoot->OwnerDoc();
|
||||
|
||||
// Parsed selectors are already cached by the document. A lone class needs
|
||||
// only an atom lookup per element, not the general CSS matching context.
|
||||
nsCSSSelector* selector = aSelectorList->mSelectors;
|
||||
if (!aSelectorList->mNext && !selector->mNext &&
|
||||
selector->mClassList && !selector->mClassList->mNext &&
|
||||
!selector->mLowercaseTag && !selector->mIDList &&
|
||||
!selector->mAttrList && !selector->mPseudoClassList &&
|
||||
!selector->mNegations && selector->mNameSpace == kNameSpaceID_Unknown &&
|
||||
selector->IsRestrictedSelector() && !selector->IsHybridPseudoElement()) {
|
||||
nsCaseTreatment caseTreatment =
|
||||
doc->GetCompatibilityMode() == eCompatibility_NavQuirks
|
||||
? eIgnoreCase : eCaseMatters;
|
||||
FindMatchingElementsWithClass<onlyFirstMatch, Collector>(
|
||||
aRoot, selector->mClassList->mAtom, caseTreatment, aList);
|
||||
return;
|
||||
}
|
||||
|
||||
TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
|
||||
doc, TreeMatchContext::eNeverMatchVisited);
|
||||
doc->FlushPendingLinkUpdates();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue