зеркало из https://github.com/mozilla/pjs.git
Bug 696205 part 2. Add a querySelector fast-path for selectors whose rightmost sequence of simple selectors contains an id. r=sicking
This commit is contained in:
Родитель
440978fc40
Коммит
5a98b45de1
|
@ -126,8 +126,8 @@ class Element;
|
|||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x3d24831e, 0x2a2b, 0x42f4, \
|
||||
{ 0x9d, 0x98, 0x17, 0x60, 0x18, 0xab, 0x6e, 0xfb } }
|
||||
{ 0xb52356d4, 0xe191, 0x4cf8, \
|
||||
{ 0xb8, 0x58, 0xc0, 0xf1, 0xe1, 0x98, 0x09, 0xdf } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -1510,6 +1510,13 @@ public:
|
|||
*/
|
||||
virtual Element* GetElementById(const nsAString& aElementId) = 0;
|
||||
|
||||
/**
|
||||
* This method returns _all_ the elements in this document which
|
||||
* have id aElementId, if there are any. Otherwise it returns null.
|
||||
* The entries of the nsSmallVoidArray are Element*
|
||||
*/
|
||||
virtual const nsSmallVoidArray* GetAllElementsForId(const nsAString& aElementId) const = 0;
|
||||
|
||||
/**
|
||||
* Lookup an image element using its associated ID, which is usually provided
|
||||
* by |-moz-element()|. Similar to GetElementById, with the difference that
|
||||
|
|
|
@ -4036,6 +4036,17 @@ nsDocument::GetElementById(const nsAString& aElementId)
|
|||
return entry ? entry->GetIdElement() : nsnull;
|
||||
}
|
||||
|
||||
const nsSmallVoidArray*
|
||||
nsDocument::GetAllElementsForId(const nsAString& aElementId) const
|
||||
{
|
||||
if (aElementId.IsEmpty()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
|
||||
return entry ? entry->GetIdElements() : nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
|
||||
{
|
||||
|
|
|
@ -171,6 +171,12 @@ public:
|
|||
* id. Otherwise returns null.
|
||||
*/
|
||||
Element* GetIdElement();
|
||||
/**
|
||||
* Returns the list of all elements associated with this id.
|
||||
*/
|
||||
const nsSmallVoidArray* GetIdElements() const {
|
||||
return &mIdContentList;
|
||||
}
|
||||
/**
|
||||
* If this entry has a non-null image element set (using SetImageElement),
|
||||
* the image element will be returned, otherwise the same as GetIdElement().
|
||||
|
@ -244,7 +250,7 @@ private:
|
|||
void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
|
||||
bool aImageOnly = false);
|
||||
|
||||
// empty if there are no elementswith this ID.
|
||||
// empty if there are no elements with this ID.
|
||||
// The elements are stored as weak pointers.
|
||||
nsSmallVoidArray mIdContentList;
|
||||
nsRefPtr<nsBaseContentList> mNameContentList;
|
||||
|
@ -926,6 +932,7 @@ public:
|
|||
const nsAString& aLocalName);
|
||||
|
||||
virtual Element *GetElementById(const nsAString& aElementId);
|
||||
virtual const nsSmallVoidArray* GetAllElementsForId(const nsAString& aElementId) const;
|
||||
|
||||
virtual Element *LookupImageElement(const nsAString& aElementId);
|
||||
|
||||
|
|
|
@ -5352,6 +5352,9 @@ ParseSelectorList(nsINode* aNode,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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 T>
|
||||
inline static nsresult FindMatchingElements(nsINode* aRoot,
|
||||
const nsAString& aSelector,
|
||||
|
@ -5361,10 +5364,55 @@ inline static nsresult FindMatchingElements(nsINode* aRoot,
|
|||
nsresult rv = ParseSelectorList(aRoot, aSelector,
|
||||
getter_Transfers(selectorList));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(selectorList, NS_OK);
|
||||
|
||||
NS_ASSERTION(selectorList->mSelectors,
|
||||
"How can we not have any selectors?");
|
||||
|
||||
nsIDocument* doc = aRoot->OwnerDoc();
|
||||
TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
|
||||
doc);
|
||||
|
||||
// Fast-path selectors involving IDs. We can only do this if aRoot
|
||||
// is in the document and the document is not in quirks mode, since
|
||||
// ID selectors are case-insensitive in quirks mode. Also, only do
|
||||
// this if selectorList only has one selector, because otherwise
|
||||
// ordering the elements correctly is a pain.
|
||||
NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT),
|
||||
"Unexpected root node");
|
||||
if (aRoot->IsInDoc() &&
|
||||
doc->GetCompatibilityMode() != eCompatibility_NavQuirks &&
|
||||
!selectorList->mNext &&
|
||||
selectorList->mSelectors->mIDList) {
|
||||
nsIAtom* id = selectorList->mSelectors->mIDList->mAtom;
|
||||
const nsSmallVoidArray* elements =
|
||||
doc->GetAllElementsForId(nsDependentAtomString(id));
|
||||
|
||||
// XXXbz: Should we fall back to the tree walk if aRoot is not the
|
||||
// document and |elements| is long, for some value of "long"?
|
||||
if (elements) {
|
||||
for (PRUint32 i = 0; i < elements->Count(); ++i) {
|
||||
Element *element = static_cast<Element*>(elements->ElementAt(i));
|
||||
if (!aRoot->IsElement() ||
|
||||
nsContentUtils::ContentIsDescendantOf(element, aRoot)) {
|
||||
// We have an element with the right id and it's a descendant
|
||||
// of aRoot. Make sure it really matches the selector.
|
||||
if (nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
|
||||
selectorList)) {
|
||||
aList.AppendElement(element);
|
||||
if (onlyFirstMatch) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No elements with this id, or none of them are our descendants,
|
||||
// or none of them match. We're done here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TreeMatchContext matchingContext(false,
|
||||
nsRuleWalker::eRelevantLinkUnvisited,
|
||||
aRoot->OwnerDoc());
|
||||
for (nsIContent* cur = aRoot->GetFirstChild();
|
||||
cur;
|
||||
cur = cur->GetNextNode(aRoot)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче