moebius#140: Fix: Fetch - headers should sort and combine

https://github.com/MoonchildProductions/moebius/pull/140
This commit is contained in:
janekptacijarabaci 2018-04-14 22:18:47 +02:00 committed by Roy Tam
commit f70e3223fb
4 changed files with 86 additions and 27 deletions

View file

@ -21,12 +21,14 @@ InternalHeaders::InternalHeaders(const nsTArray<Entry>&& aHeaders,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
, mList(aHeaders)
, mListDirty(true)
{
}
InternalHeaders::InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
HeadersGuardEnum aGuard)
: mGuard(aGuard)
, mListDirty(true)
{
for (const HeadersEntry& headersEntry : aHeadersEntryList) {
mList.AppendElement(Entry(headersEntry.name(), headersEntry.value()));
@ -56,6 +58,8 @@ InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
return;
}
SetListDirty();
mList.AppendElement(Entry(lowerName, aValue));
}
@ -69,6 +73,8 @@ InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
return;
}
SetListDirty();
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
@ -155,6 +161,8 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
return;
}
SetListDirty();
int32_t firstIndex = INT32_MAX;
// remove in reverse order to minimize copying
@ -177,6 +185,7 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
void
InternalHeaders::Clear()
{
SetListDirty();
mList.Clear();
}
@ -419,5 +428,54 @@ InternalHeaders::GetUnsafeHeaders(nsTArray<nsCString>& aNames) const
}
}
void
InternalHeaders::MaybeSortList()
{
class Comparator {
public:
bool Equals(const Entry& aA, const Entry& aB) const
{
return aA.mName == aB.mName;
}
bool LessThan(const Entry& aA, const Entry& aB) const
{
return aA.mName < aB.mName;
}
};
if (!mListDirty) {
return;
}
mListDirty = false;
Comparator comparator;
mSortedList.Clear();
for (const Entry& entry : mList) {
bool found = false;
for (Entry& sortedEntry : mSortedList) {
if (sortedEntry.mName == entry.mName) {
sortedEntry.mValue += ", ";
sortedEntry.mValue += entry.mValue;
found = true;
break;
}
}
if (!found) {
mSortedList.InsertElementSorted(entry, comparator);
}
}
}
void
InternalHeaders::SetListDirty()
{
mSortedList.Clear();
mListDirty = true;
}
} // namespace dom
} // namespace mozilla

View file

@ -45,14 +45,23 @@ private:
HeadersGuardEnum mGuard;
nsTArray<Entry> mList;
nsTArray<Entry> mSortedList;
// This boolean is set to true at any writing operation to mList. It's set to
// false when mSortedList is regenerated. This happens when the header is
// iterated.
bool mListDirty;
public:
explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None)
: mGuard(aGuard)
, mListDirty(false)
{
}
explicit InternalHeaders(const InternalHeaders& aOther)
: mGuard(HeadersGuardEnum::None)
, mListDirty(true)
{
ErrorResult result;
Fill(aOther, result);
@ -79,19 +88,22 @@ public:
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
uint32_t GetIterableLength() const
uint32_t GetIterableLength()
{
return mList.Length();
MaybeSortList();
return mSortedList.Length();
}
const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) const
const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex)
{
MOZ_ASSERT(aIndex < mList.Length());
return NS_ConvertASCIItoUTF16(mList[aIndex].mName);
MaybeSortList();
MOZ_ASSERT(aIndex < mSortedList.Length());
return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mName);
}
const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) const
const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex)
{
MOZ_ASSERT(aIndex < mList.Length());
return NS_ConvertASCIItoUTF16(mList[aIndex].mValue);
MaybeSortList();
MOZ_ASSERT(aIndex < mSortedList.Length());
return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mValue);
}
void Clear();
@ -152,6 +164,9 @@ private:
const nsACString& aValue);
static bool IsRevalidationHeader(const nsACString& aName);
void MaybeSortList();
void SetListDirty();
};
} // namespace dom

View file

@ -213,12 +213,12 @@ function TestHeadersIterator() {
var value_iter = headers.values();
var entries_iter = headers.entries();
arrayEquals(iterate(key_iter), ["foo", "foo", "foo2"], "Correct key iterator");
arrayEquals(iterate(value_iter), ["bar", ehsanInflated, "baz2"], "Correct value iterator");
arrayEquals(iterate(entries_iter), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator");
arrayEquals(iterate(value_iter), ["bar, " + ehsanInflated, "baz2"], "Correct value iterator");
arrayEquals(iterate(entries_iter), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(headers), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(headers), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar, " + ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
}
function runTest() {

View file

@ -1,17 +1,3 @@
[headers-basic.html]
type: testharness
[Check keys method]
expected: FAIL
[Check values method]
expected: FAIL
[Check entries method]
expected: FAIL
[Check Symbol.iterator method]
expected: FAIL
[Check forEach method]
expected: FAIL