diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp
index d5b7a969ffe..3a1a126139f 100644
--- a/mozilla/content/html/document/src/nsHTMLDocument.cpp
+++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp
@@ -2377,12 +2377,25 @@ nsHTMLDocument::GetElementById(const nsAString& aElementId,
}
if (!e) {
- NS_WARN_IF_FALSE(!aElementId.IsEmpty(),
- "getElementById(\"\") called, fix caller?");
+ // If IdTableIsLive(), no need to look for the element in the document,
+ // since we're fully maintaining our table's state as the DOM mutates.
+ if (!IdTableIsLive()) {
+ if (IdTableShouldBecomeLive()) {
+ // Just make sure our table is up to date and call this method again
+ // to look up in the hashtable.
+ if (mRootContent) {
+ RegisterNamedItems(mRootContent);
+ }
+ return GetElementById(aElementId, aReturn);
+ }
- if (mRootContent && !aElementId.IsEmpty()) {
- e = MatchElementId(mRootContent, NS_ConvertUCS2toUTF8(aElementId),
- aElementId);
+ NS_WARN_IF_FALSE(!aElementId.IsEmpty(),
+ "getElementById(\"\") called, fix caller?");
+
+ if (mRootContent && !aElementId.IsEmpty()) {
+ e = MatchElementId(mRootContent, NS_ConvertUCS2toUTF8(aElementId),
+ aElementId);
+ }
}
if (!e) {
@@ -3015,12 +3028,14 @@ nsHTMLDocument::AddToIdTable(const nsAString& aId, nsIContent *aContent)
nsresult
nsHTMLDocument::UpdateIdTableEntry(const nsAString& aId, nsIContent *aContent)
{
+ PRBool liveTable = IdTableIsLive();
+ PLDHashOperator op = liveTable ? PL_DHASH_ADD : PL_DHASH_LOOKUP;
IdAndNameMapEntry *entry =
NS_STATIC_CAST(IdAndNameMapEntry *,
PL_DHashTableOperate(&mIdAndNameHashTable, &aId,
- PL_DHASH_LOOKUP));
+ op));
- if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
+ if (entry && (liveTable || PL_DHASH_ENTRY_IS_BUSY(entry))) {
entry->mIdContent = aContent;
}
diff --git a/mozilla/content/html/document/src/nsHTMLDocument.h b/mozilla/content/html/document/src/nsHTMLDocument.h
index 46b79d6e616..eb7edce8ec1 100644
--- a/mozilla/content/html/document/src/nsHTMLDocument.h
+++ b/mozilla/content/html/document/src/nsHTMLDocument.h
@@ -310,6 +310,27 @@ protected:
PRPackedBool mIsFrameset;
+ PRBool IdTableIsLive() const {
+ // live if we've had over 63 misses
+ return (mIdMissCount & 0x40) != 0;
+ }
+
+ PRBool IdTableShouldBecomeLive() {
+ NS_ASSERTION(!IdTableIsLive(),
+ "Shouldn't be called if table is already live!");
+ ++mIdMissCount;
+ return IdTableIsLive();
+ }
+
+ PRUint8 mIdMissCount;
+
+ /* mIdAndNameHashTable works as follows for IDs:
+ * 1) Attribute changes affect the table immediately (removing and adding
+ * entries as needed).
+ * 2) Removals from the DOM affect the table immediately
+ * 3) Additions to the DOM always update existing entries, but only add new
+ * ones if IdTableIsLive() is true.
+ */
PLDHashTable mIdAndNameHashTable;
nsCOMPtr mWyciwygChannel;