mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Fixing bug 572614. Eliminate double hash lookups in document.getElementById(). r=jonas@sicking.cc
This commit is contained in:
parent
c50fb5d521
commit
4548ec1aa1
@ -2337,7 +2337,8 @@ nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName)
|
||||
if (!mIsRegularHTML)
|
||||
return;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.GetEntry(nsDependentAtomString(aName));
|
||||
|
||||
// entry is null if we're not tracking the elements with this name
|
||||
|
||||
@ -2353,7 +2354,8 @@ nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName)
|
||||
if (!mIsRegularHTML || mIdentifierMap.Count() == 0)
|
||||
return;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.GetEntry(nsDependentAtomString(aName));
|
||||
if (!entry) // Should never be false unless we had OOM when adding the entry
|
||||
return;
|
||||
|
||||
@ -2363,7 +2365,8 @@ nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName)
|
||||
void
|
||||
nsDocument::AddToIdTable(Element *aElement, nsIAtom* aId)
|
||||
{
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aId);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.PutEntry(nsDependentAtomString(aId));
|
||||
|
||||
if (entry) { /* True except on OOM */
|
||||
entry->AddIdElement(aElement);
|
||||
@ -2380,12 +2383,13 @@ nsDocument::RemoveFromIdTable(Element *aElement, nsIAtom* aId)
|
||||
return;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aId);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.GetEntry(nsDependentAtomString(aId));
|
||||
if (!entry) // Can be null for XML elements with changing ids.
|
||||
return;
|
||||
|
||||
if (entry->RemoveIdElement(aElement)) {
|
||||
mIdentifierMap.RemoveEntry(aId);
|
||||
mIdentifierMap.RawRemoveEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3721,38 +3725,27 @@ nsDocument::BeginLoad()
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginLoad, (this));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDocument::CheckGetElementByIdArg(const nsIAtom* aId)
|
||||
// static
|
||||
void
|
||||
nsDocument::ReportEmptyGetElementByIdArg()
|
||||
{
|
||||
if (aId == nsGkAtoms::_empty) {
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"EmptyGetElementByIdParam",
|
||||
nsnull, 0,
|
||||
nsnull,
|
||||
EmptyString(), 0, 0,
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM");
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
|
||||
"EmptyGetElementByIdParam",
|
||||
nsnull, 0,
|
||||
nsnull,
|
||||
EmptyString(), 0, 0,
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM");
|
||||
}
|
||||
|
||||
Element*
|
||||
nsDocument::GetElementById(const nsAString& aElementId)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> idAtom(do_GetAtom(aElementId));
|
||||
if (!idAtom) {
|
||||
// This can only fail due to OOM when the atom doesn't exist, in which
|
||||
// case there can't be an entry for it.
|
||||
if (!CheckGetElementByIdArg(aElementId)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!CheckGetElementByIdArg(idAtom)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(idAtom);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
|
||||
return entry ? entry->GetIdElement() : nsnull;
|
||||
}
|
||||
|
||||
@ -3773,10 +3766,12 @@ Element*
|
||||
nsDocument::AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver,
|
||||
void* aData)
|
||||
{
|
||||
if (!CheckGetElementByIdArg(aID))
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id))
|
||||
return nsnull;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aID);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(id);
|
||||
NS_ENSURE_TRUE(entry, nsnull);
|
||||
|
||||
entry->AddContentChangeCallback(aObserver, aData);
|
||||
@ -3787,10 +3782,12 @@ void
|
||||
nsDocument::RemoveIDTargetObserver(nsIAtom* aID,
|
||||
IDTargetObserver aObserver, void* aData)
|
||||
{
|
||||
if (!CheckGetElementByIdArg(aID))
|
||||
nsDependentAtomString id(aID);
|
||||
|
||||
if (!CheckGetElementByIdArg(id))
|
||||
return;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aID);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(id);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
@ -145,17 +145,21 @@ class nsHTMLCSSStyleSheet;
|
||||
* Perhaps the document.all results should have their own hashtable
|
||||
* in nsHTMLDocument.
|
||||
*/
|
||||
class nsIdentifierMapEntry : public nsISupportsHashKey
|
||||
class nsIdentifierMapEntry : public nsStringHashKey
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
|
||||
nsIdentifierMapEntry(const nsISupports* aKey) :
|
||||
nsISupportsHashKey(aKey), mNameContentList(nsnull)
|
||||
nsIdentifierMapEntry(const nsAString& aKey) :
|
||||
nsStringHashKey(&aKey), mNameContentList(nsnull)
|
||||
{
|
||||
}
|
||||
nsIdentifierMapEntry(const nsAString *aKey) :
|
||||
nsStringHashKey(aKey), mNameContentList(nsnull)
|
||||
{
|
||||
}
|
||||
nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) :
|
||||
nsISupportsHashKey(GetKey())
|
||||
nsStringHashKey(&aOther.GetKey())
|
||||
{
|
||||
NS_ERROR("Should never be called");
|
||||
}
|
||||
@ -951,7 +955,16 @@ protected:
|
||||
* service if it is.
|
||||
* @returns PR_TRUE if aId looks correct, PR_FALSE otherwise.
|
||||
*/
|
||||
static PRBool CheckGetElementByIdArg(const nsIAtom* aId);
|
||||
static inline PRBool CheckGetElementByIdArg(const nsAString& aId)
|
||||
{
|
||||
if (aId.IsEmpty()) {
|
||||
ReportEmptyGetElementByIdArg();
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static void ReportEmptyGetElementByIdArg();
|
||||
|
||||
void DispatchContentLoadedEvents();
|
||||
|
||||
|
@ -2677,11 +2677,9 @@ nsHTMLDocument::ResolveName(const nsAString& aName,
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAtom> name(do_GetAtom(aName));
|
||||
|
||||
// We have built a table and cache the named items. The table will
|
||||
// be updated as content is added and removed.
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(name);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aName);
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (entry->IsInvalidName()) {
|
||||
@ -2705,7 +2703,14 @@ nsHTMLDocument::ResolveName(const nsAString& aName,
|
||||
|
||||
Element* root = GetRootElement();
|
||||
if (root && !aName.IsEmpty()) {
|
||||
FindNamedItems(name, root, entry);
|
||||
// do_GetAtom() can fail on OOM, but it'll only do that if the
|
||||
// atom doesn't already exist, which means the named item
|
||||
// doesn't exist either.
|
||||
nsCOMPtr<nsIAtom> name(do_GetAtom(aName));
|
||||
|
||||
if (name) {
|
||||
FindNamedItems(name, root, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2810,7 +2815,8 @@ nsHTMLDocument::PrePopulateIdentifierMap()
|
||||
nsCOMPtr<nsIAtom> atom(do_GetAtom(names[i]));
|
||||
NS_ENSURE_TRUE(atom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(atom);
|
||||
nsIdentifierMapEntry* entry =
|
||||
mIdentifierMap.PutEntry(nsDependentAtomString(atom));
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
entry->SetInvalidName();
|
||||
@ -3135,8 +3141,7 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAtom> id = do_GetAtom(aID);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(id);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aID);
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
Element* root = GetRootElement();
|
||||
@ -3146,6 +3151,8 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult
|
||||
|
||||
nsRefPtr<nsContentList> docAllList = entry->GetDocAllList();
|
||||
if (!docAllList) {
|
||||
nsCOMPtr<nsIAtom> id = do_GetAtom(aID);
|
||||
|
||||
docAllList = new nsContentList(root, DocAllResultMatch,
|
||||
nsnull, nsnull, PR_TRUE, id);
|
||||
NS_ENSURE_TRUE(docAllList, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -1142,7 +1142,7 @@ nsXULDocument::GetElementsForID(const nsAString& aID,
|
||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(aID);
|
||||
if (!atom)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom);
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aID);
|
||||
if (entry) {
|
||||
entry->AppendAllIdContent(&aElements);
|
||||
}
|
||||
@ -1639,6 +1639,16 @@ nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker)
|
||||
Element*
|
||||
nsXULDocument::GetElementById(const nsAString& aId)
|
||||
{
|
||||
if (!CheckGetElementByIdArg(aId))
|
||||
return nsnull;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aId);
|
||||
if (entry) {
|
||||
Element* element = entry->GetIdElement();
|
||||
if (element)
|
||||
return element;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> atom(do_GetAtom(aId));
|
||||
if (!atom) {
|
||||
// This can only fail due OOM if the atom doesn't exist, in which
|
||||
@ -1646,15 +1656,6 @@ nsXULDocument::GetElementById(const nsAString& aId)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!CheckGetElementByIdArg(atom))
|
||||
return nsnull;
|
||||
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom);
|
||||
if (entry) {
|
||||
Element* element = entry->GetIdElement();
|
||||
if (element)
|
||||
return element;
|
||||
}
|
||||
nsRefMapEntry* refEntry = mRefMap.GetEntry(atom);
|
||||
if (refEntry) {
|
||||
NS_ASSERTION(refEntry->GetFirstElement(),
|
||||
|
Loading…
Reference in New Issue
Block a user