diff --git a/content/base/src/nsContentList.cpp b/content/base/src/nsContentList.cpp index 64250249f2ec..8a34cddca6e6 100644 --- a/content/base/src/nsContentList.cpp +++ b/content/base/src/nsContentList.cpp @@ -130,17 +130,6 @@ nsBaseContentList::GetNodeAt(PRUint32 aIndex) return mElements.SafeObjectAt(aIndex); } -void -nsBaseContentList::AppendElement(nsIContent *aContent) -{ - mElements.AppendObject(aContent); -} - -void -nsBaseContentList::RemoveElement(nsIContent *aContent) -{ - mElements.RemoveObject(aContent); -} PRInt32 nsBaseContentList::IndexOf(nsIContent *aContent, PRBool aDoFlush) @@ -154,20 +143,27 @@ nsBaseContentList::IndexOf(nsIContent* aContent) return IndexOf(aContent, PR_TRUE); } -void -nsBaseContentList::Reset() +void nsBaseContentList::AppendElement(nsIContent *aContent) { - mElements.Clear(); + mElements.AppendObject(aContent); } -// static -void -nsBaseContentList::Shutdown() +void nsBaseContentList::RemoveElement(nsIContent *aContent) { + mElements.RemoveObject(aContent); +} + +void nsBaseContentList::InsertElementAt(nsIContent* aContent, PRInt32 aIndex) +{ + NS_ASSERTION(aContent, "Element to insert must not be null"); + mElements.InsertObjectAt(aContent, aIndex); +} + +//static +void nsBaseContentList::Shutdown() { NS_IF_RELEASE(gCachedContentList); } - // nsFormContentList nsFormContentList::nsFormContentList(nsIDOMHTMLFormElement *aForm, diff --git a/content/base/src/nsContentList.h b/content/base/src/nsContentList.h index c871625b566e..897fbcbd89aa 100644 --- a/content/base/src/nsContentList.h +++ b/content/base/src/nsContentList.h @@ -89,12 +89,30 @@ public: virtual nsIContent* GetNodeAt(PRUint32 aIndex); virtual PRInt32 IndexOf(nsIContent* aContent); + PRUint32 Length() const { + return mElements.Count(); + } + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsBaseContentList, nsINodeList) void AppendElement(nsIContent *aContent); - void RemoveElement(nsIContent *aContent); + + /** + * Insert the element at a given index, shifting the objects at + * the given index and later to make space. + * @param aContent Element to insert, must not be null + * @param aIndex Index to insert the element at. + */ + void InsertElementAt(nsIContent* aContent, PRInt32 aIndex); + + void RemoveElement(nsIContent *aContent); + + void Reset() { + mElements.Clear(); + } + + virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush); - void Reset(); static void Shutdown(); diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 4984f28b344f..d33f4dffe016 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -2253,10 +2253,14 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, nsBaseContentList *list = new nsBaseContentList(); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - list->AppendElement(content); + NS_ASSERTION(content->GetParent(), "Item in list without parent"); + + // Determine the ordering between the new and old element. + PRBool newFirst = nsContentUtils::PositionIsBefore(newChild, content); + + list->AppendElement(newFirst ? newChild : content); + list->AppendElement(newFirst ? content : newChild); - // Add the new child too - list->AppendElement(newChild); nsCOMPtr listSupports = do_QueryInterface(static_cast(list)); @@ -2273,12 +2277,31 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, nsBaseContentList *list = static_cast ((nsIDOMNodeList *)nodeList.get()); - PRInt32 oldIndex = list->IndexOf(newChild, PR_FALSE); + NS_ASSERTION(list->Length() > 1, + "List should have been converted back to a single element"); - // Add the new child only if it's not in our list already - if (oldIndex < 0) { - list->AppendElement(newChild); + if(nsContentUtils::PositionIsBefore(list->GetNodeAt(list->Length() - 1), newChild)) { + list->AppendElement(newChild); + return NS_OK; } + + // first is the first possible insertion index, last is the last possible + // insertion index + PRUint32 first = 0; + PRUint32 last = list->Length() - 1; + PRUint32 mid; + + //Stop when there is only one index in our range + while (last != first) { + mid = (first + last) / 2; + + if (nsContentUtils::PositionIsBefore(newChild, list->GetNodeAt(mid))) + last = mid; + else + first = mid + 1; + } + + list->InsertElementAt(newChild, first); } } diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index aad17f2ef5d3..975f01c73603 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -83,6 +83,7 @@ _TEST_FILES = test_bug589.html \ test_bug332893-4.html \ test_bug332893-5.html \ test_bug332893-6.html \ + test_bug332893-7.html \ bug340800_iframe.txt \ test_bug340800.html \ test_bug353415-1.html \ diff --git a/content/html/content/test/test_bug332893-4.html b/content/html/content/test/test_bug332893-4.html index b64160d5ac8e..91d3cc75dcc7 100644 --- a/content/html/content/test/test_bug332893-4.html +++ b/content/html/content/test/test_bug332893-4.html @@ -18,13 +18,13 @@ form1.insertBefore(input2, input1); is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length"); - todo(form1.elements["input"][0].value == "2", "Form 1 element 1 is correct"); - todo(form1.elements["input"][1].value == "1", "Form 1 element 2 is correct"); - todo(form1.elements["input"][2].value == "3", "Form 1 element 3 is correct"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); + is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct"); - todo(form1.elements["input"][0].id == "input2", "Form 1 element 1 id is correct"); - todo(form1.elements["input"][1].id == "input1", "Form 1 element 2 id is correct"); - todo(form1.elements["input"][2].id == "input3", "Form 1 element 3 id is correct"); + is(form1.elements["input"][0].id, "input2", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); + is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct"); diff --git a/content/html/content/test/test_bug332893-5.html b/content/html/content/test/test_bug332893-5.html index b73332e7b3fc..74b54a0ab006 100644 --- a/content/html/content/test/test_bug332893-5.html +++ b/content/html/content/test/test_bug332893-5.html @@ -18,13 +18,13 @@ form1.insertBefore(input2, input1); is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length"); - todo(form1.elements["input"][0].value == "2", "Form 1 element 1 is correct"); - todo(form1.elements["input"][1].value == "1", "Form 1 element 2 is correct"); - todo(form1.elements["input"][2].value == "3", "Form 1 element 3 is correct"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); + is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct"); - todo(form1.elements["input"][0].id == "input", "Form 1 element 1 id is correct"); - todo(form1.elements["input"][1].id == "input1", "Form 1 element 2 id is correct"); - todo(form1.elements["input"][2].id == "input3", "Form 1 element 3 id is correct"); + is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); + is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct"); diff --git a/content/html/content/test/test_bug332893-6.html b/content/html/content/test/test_bug332893-6.html index 2e26be005de5..86e483d2b844 100644 --- a/content/html/content/test/test_bug332893-6.html +++ b/content/html/content/test/test_bug332893-6.html @@ -18,11 +18,11 @@ form1.insertBefore(input2, input1); is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length"); - todo(form1.elements["input"][0].value == "2", "Form 1 element 1 is correct"); - todo(form1.elements["input"][1].value == "1", "Form 1 element 2 is correct"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); - todo(form1.elements["input"][0].id == "input", "Form 1 element 1 id is correct"); - todo(form1.elements["input"][1].id == "input1", "Form 1 element 2 id is correct"); + is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); diff --git a/content/html/content/test/test_bug332893-7.html b/content/html/content/test/test_bug332893-7.html new file mode 100644 index 000000000000..efa96ff73633 --- /dev/null +++ b/content/html/content/test/test_bug332893-7.html @@ -0,0 +1,70 @@ + + + + Test + + + + +
+ + + + + + + + + + + + + + +
+ + +