author | Andrea Marchesini <amarchesini@mozilla.com> |
Tue, 20 Oct 2015 04:06:00 +0200 | |
changeset 303688 | 512b90a0f35f1e06ad74e920f892cda0d6039f7c |
parent 303687 | 6847cbf4180aba4ece3fca0f1b719007ae598f5d |
child 303689 | aa49df6c573f421f74f1eaf17d94a87d41d75a7c |
push id | 1001 |
push user | raliiev@mozilla.com |
push date | Mon, 18 Jan 2016 19:06:03 +0000 |
treeherder | mozilla-release@8b89261f3ac4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bz |
bugs | 1127703 |
milestone | 44.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -857,39 +857,40 @@ WriteFormData(JSStructuredCloneWriter* a public: Closure(JSStructuredCloneWriter* aWriter, StructuredCloneHolder* aHolder) : mWriter(aWriter), mHolder(aHolder) { } static bool - Write(const nsString& aName, bool isFile, const nsString& aValue, - File* aFile, void* aClosure) + Write(const nsString& aName, const OwningFileOrUSVString& aValue, + void* aClosure) { Closure* closure = static_cast<Closure*>(aClosure); if (!WriteString(closure->mWriter, aName)) { return false; } - if (isFile) { - BlobImpl* blobImpl = aFile->Impl(); + if (aValue.IsFile()) { + BlobImpl* blobImpl = aValue.GetAsFile()->Impl(); if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB, closure->mHolder->BlobImpls().Length())) { return false; } closure->mHolder->BlobImpls().AppendElement(blobImpl); return true; } size_t charSize = sizeof(nsString::char_type); - if (!JS_WriteUint32Pair(closure->mWriter, 0, aValue.Length()) || - !JS_WriteBytes(closure->mWriter, aValue.get(), - aValue.Length() * charSize)) { + if (!JS_WriteUint32Pair(closure->mWriter, 0, + aValue.GetAsUSVString().Length()) || + !JS_WriteBytes(closure->mWriter, aValue.GetAsUSVString().get(), + aValue.GetAsUSVString().Length() * charSize)) { return false; } return true; } }; Closure closure(aWriter, aHolder); return aFormData->ForEach(Closure::Write, &closure);
--- a/dom/base/nsFormData.cpp +++ b/dom/base/nsFormData.cpp @@ -56,28 +56,28 @@ CreateNewFileInstance(Blob& aBlob, const // nsISupports NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormData) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner) for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { - ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue); + ImplCycleCollectionUnlink(tmp->mFormData[i].value); } NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { - ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue, - "mFormData[i].fileValue", 0); + ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value, + "mFormData[i].GetAsFile()", 0); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsFormData) NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormData) @@ -122,48 +122,37 @@ nsFormData::Delete(const nsAString& aNam for (uint32_t i = mFormData.Length(); i-- > 0; ) { if (aName.Equals(mFormData[i].name)) { mFormData.RemoveElementAt(i); } } } void -nsFormData::ExtractValue(const FormDataTuple& aTuple, - OwningFileOrUSVString* aOutValue) -{ - if (aTuple.valueIsFile) { - aOutValue->SetAsFile() = aTuple.fileValue; - } else { - aOutValue->SetAsUSVString() = aTuple.stringValue; - } -} - -void nsFormData::Get(const nsAString& aName, Nullable<OwningFileOrUSVString>& aOutValue) { for (uint32_t i = 0; i < mFormData.Length(); ++i) { if (aName.Equals(mFormData[i].name)) { - ExtractValue(mFormData[i], &aOutValue.SetValue()); + aOutValue.SetValue() = mFormData[i].value; return; } } aOutValue.SetNull(); } void nsFormData::GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues) { for (uint32_t i = 0; i < mFormData.Length(); ++i) { if (aName.Equals(mFormData[i].name)) { OwningFileOrUSVString* element = aValues.AppendElement(); - ExtractValue(mFormData[i], element); + *element = mFormData[i].value; } } } bool nsFormData::Has(const nsAString& aName) { for (uint32_t i = 0; i < mFormData.Length(); ++i) { @@ -224,16 +213,36 @@ nsFormData::Set(const nsAString& aName, FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); if (tuple) { SetNameValuePair(tuple, aName, aValue); } else { Append(aName, aValue); } } +uint32_t +nsFormData::GetIterableLength() const +{ + return mFormData.Length(); +} + +const nsAString& +nsFormData::GetKeyAtIndex(uint32_t aIndex) const +{ + MOZ_ASSERT(aIndex < mFormData.Length()); + return mFormData[aIndex].name; +} + +const OwningFileOrUSVString& +nsFormData::GetValueAtIndex(uint32_t aIndex) const +{ + MOZ_ASSERT(aIndex < mFormData.Length()); + return mFormData[aIndex].value; +} + // ------------------------------------------------------------------------- // nsIDOMFormData NS_IMETHODIMP nsFormData::Append(const nsAString& aName, nsIVariant* aValue) { uint16_t dataType; nsresult rv = aValue->GetDataType(&dataType); @@ -292,21 +301,23 @@ nsFormData::Constructor(const GlobalObje NS_IMETHODIMP nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength, nsACString& aContentType, nsACString& aCharset) { nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr); for (uint32_t i = 0; i < mFormData.Length(); ++i) { - if (mFormData[i].valueIsFile) { - fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue); - } - else { - fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue); + if (mFormData[i].value.IsFile()) { + fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile()); + } else if (mFormData[i].value.IsUSVString()) { + fs.AddNameValuePair(mFormData[i].name, + mFormData[i].value.GetAsUSVString()); + } else { + fs.AddNameFilePair(mFormData[i].name, nullptr); } } fs.GetContentType(aContentType); aCharset.Truncate(); *aContentLength = 0; NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));
--- a/dom/base/nsFormData.h +++ b/dom/base/nsFormData.h @@ -32,52 +32,49 @@ class nsFormData final : public nsIDOMFo public nsFormSubmission, public nsWrapperCache { private: ~nsFormData() {} typedef mozilla::dom::Blob Blob; typedef mozilla::dom::File File; + typedef mozilla::dom::OwningFileOrUSVString OwningFileOrUSVString; struct FormDataTuple { nsString name; - nsString stringValue; - RefPtr<File> fileValue; - bool valueIsFile; + OwningFileOrUSVString value; }; // Returns the FormDataTuple to modify. This may be null, in which case // no element with aName was found. FormDataTuple* RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName); void SetNameValuePair(FormDataTuple* aData, const nsAString& aName, const nsAString& aValue) { MOZ_ASSERT(aData); aData->name = aName; - aData->stringValue = aValue; - aData->valueIsFile = false; + aData->value.SetAsUSVString() = aValue; } void SetNameFilePair(FormDataTuple* aData, const nsAString& aName, File* aFile) { MOZ_ASSERT(aData); aData->name = aName; - aData->fileValue = aFile; - aData->valueIsFile = true; + if (aFile) { + aData->value.SetAsFile() = aFile; + } } - void ExtractValue(const FormDataTuple& aTuple, - mozilla::dom::OwningFileOrUSVString* aOutValue); public: explicit nsFormData(nsISupports* aOwner = nullptr); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFormData, nsIDOMFormData) NS_DECL_NSIDOMFORMDATA @@ -95,55 +92,58 @@ public: static already_AddRefed<nsFormData> Constructor(const mozilla::dom::GlobalObject& aGlobal, const mozilla::dom::Optional<mozilla::dom::NonNull<mozilla::dom::HTMLFormElement> >& aFormElement, mozilla::ErrorResult& aRv); void Append(const nsAString& aName, const nsAString& aValue); void Append(const nsAString& aName, Blob& aBlob, const mozilla::dom::Optional<nsAString>& aFilename); void Delete(const nsAString& aName); - void Get(const nsAString& aName, mozilla::dom::Nullable<mozilla::dom::OwningFileOrUSVString>& aOutValue); - void GetAll(const nsAString& aName, nsTArray<mozilla::dom::OwningFileOrUSVString>& aValues); + void Get(const nsAString& aName, mozilla::dom::Nullable<OwningFileOrUSVString>& aOutValue); + void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues); bool Has(const nsAString& aName); void Set(const nsAString& aName, Blob& aBlob, const mozilla::dom::Optional<nsAString>& aFilename); void Set(const nsAString& aName, const nsAString& aValue); + uint32_t GetIterableLength() const; + const nsAString& GetKeyAtIndex(uint32_t aIndex) const; + const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const; + // nsFormSubmission virtual nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override; virtual nsresult AddNameValuePair(const nsAString& aName, const nsAString& aValue) override { FormDataTuple* data = mFormData.AppendElement(); SetNameValuePair(data, aName, aValue); return NS_OK; } virtual nsresult AddNameFilePair(const nsAString& aName, File* aFile) override; - typedef bool (*FormDataEntryCallback)(const nsString& aName, bool aIsFile, - const nsString& aValue, - File* aFile, void* aClosure); + typedef bool (*FormDataEntryCallback)(const nsString& aName, + const OwningFileOrUSVString& aValue, + void* aClosure); uint32_t Length() const { return mFormData.Length(); } // Stops iteration and returns false if any invocation of callback returns // false. Returns true otherwise. bool ForEach(FormDataEntryCallback aFunc, void* aClosure) { for (uint32_t i = 0; i < mFormData.Length(); ++i) { FormDataTuple& tuple = mFormData[i]; - if (!aFunc(tuple.name, tuple.valueIsFile, tuple.stringValue, - tuple.fileValue, aClosure)) { + if (!aFunc(tuple.name, tuple.value, aClosure)) { return false; } } return true; } private:
--- a/dom/html/test/formData_test.js +++ b/dom/html/test/formData_test.js @@ -100,16 +100,66 @@ function testFilename() { file = new File(["hi"], "file2.txt"); f.append("file2", file, "fakename.txt"); ok(f.get("file2") !== file, "Retrieved File object should be new File object if explicit filename is passed."); is(f.get("file2").name, "fakename.txt", "File's filename should be explicitly passed name."); f.append("file3", new File(["hi"], "")); is(f.get("file3").name, "", "File's filename is returned even if empty."); } +function testIterable() { + var fd = new FormData(); + fd.set('1','2'); + fd.set('2','4'); + fd.set('3','6'); + fd.set('4','8'); + fd.set('5','10'); + + var key_iter = fd.keys(); + var value_iter = fd.values(); + var entries_iter = fd.entries(); + for (var i = 0; i < 5; ++i) { + var v = i + 1; + var key = key_iter.next(); + var value = value_iter.next(); + var entry = entries_iter.next(); + is(key.value, v.toString(), "Correct Key iterator: " + v.toString()); + ok(!key.done, "key.done is false"); + is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString()); + ok(!value.done, "value.done is false"); + is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString()); + is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString()); + ok(!entry.done, "entry.done is false"); + } + + var last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); + + last = value_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last value"); + + last = entries_iter.next(); + ok(last.done, "Nothing more to read."); + + key_iter = fd.keys(); + key_iter.next(); + key_iter.next(); + fd.delete('1'); + fd.delete('2'); + fd.delete('3'); + fd.delete('4'); + fd.delete('5'); + + last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); +} + function testSend(doneCb) { var xhr = new XMLHttpRequest(); xhr.open("POST", "form_submit_server.sjs"); xhr.onload = function () { var response = xhr.response; for (var entry of response) { is(entry.body, 'hey'); @@ -156,12 +206,13 @@ function testSend(doneCb) { function runTest(doneCb) { testHas(); testGet(); testGetAll(); testDelete(); testSet(); testIterate(); testFilename(); + testIterable(); // Finally, send an XHR and verify the response matches. testSend(doneCb); }
--- a/dom/webidl/FormData.webidl +++ b/dom/webidl/FormData.webidl @@ -15,10 +15,10 @@ interface FormData { void append(USVString name, Blob value, optional USVString filename); void append(USVString name, USVString value); void delete(USVString name); FormDataEntryValue? get(USVString name); sequence<FormDataEntryValue> getAll(USVString name); boolean has(USVString name); void set(USVString name, Blob value, optional USVString filename); void set(USVString name, USVString value); - // iterable<USVString, FormDataEntryValue>; - Bug 1127703 + iterable<USVString, FormDataEntryValue>; };