Bug 1127703 - Support iteration on FormData, r=bz

This commit is contained in:
Andrea Marchesini 2015-10-19 19:23:52 +01:00
Родитель cc10dd7ad3
Коммит c628603a97
5 изменённых файлов: 106 добавлений и 45 удалений

Просмотреть файл

@ -862,16 +862,16 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
{ } { }
static bool static bool
Write(const nsString& aName, bool isFile, const nsString& aValue, Write(const nsString& aName, const OwningFileOrUSVString& aValue,
File* aFile, void* aClosure) void* aClosure)
{ {
Closure* closure = static_cast<Closure*>(aClosure); Closure* closure = static_cast<Closure*>(aClosure);
if (!WriteString(closure->mWriter, aName)) { if (!WriteString(closure->mWriter, aName)) {
return false; return false;
} }
if (isFile) { if (aValue.IsFile()) {
BlobImpl* blobImpl = aFile->Impl(); BlobImpl* blobImpl = aValue.GetAsFile()->Impl();
if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB, if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB,
closure->mHolder->BlobImpls().Length())) { closure->mHolder->BlobImpls().Length())) {
return false; return false;
@ -882,9 +882,10 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
} }
size_t charSize = sizeof(nsString::char_type); size_t charSize = sizeof(nsString::char_type);
if (!JS_WriteUint32Pair(closure->mWriter, 0, aValue.Length()) || if (!JS_WriteUint32Pair(closure->mWriter, 0,
!JS_WriteBytes(closure->mWriter, aValue.get(), aValue.GetAsUSVString().Length()) ||
aValue.Length() * charSize)) { !JS_WriteBytes(closure->mWriter, aValue.GetAsUSVString().get(),
aValue.GetAsUSVString().Length() * charSize)) {
return false; return false;
} }

Просмотреть файл

@ -61,7 +61,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue); if (tmp->mFormData[i].value.IsFile()) {
ImplCycleCollectionUnlink(tmp->mFormData[i].value);
}
} }
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@ -71,8 +73,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue, ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value,
"mFormData[i].fileValue", 0); "mFormData[i].GetAsFile()", 0);
} }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
@ -126,24 +128,13 @@ nsFormData::Delete(const nsAString& aName)
} }
} }
void
nsFormData::ExtractValue(const FormDataTuple& aTuple,
OwningFileOrUSVString* aOutValue)
{
if (aTuple.valueIsFile) {
aOutValue->SetAsFile() = aTuple.fileValue;
} else {
aOutValue->SetAsUSVString() = aTuple.stringValue;
}
}
void void
nsFormData::Get(const nsAString& aName, nsFormData::Get(const nsAString& aName,
Nullable<OwningFileOrUSVString>& aOutValue) Nullable<OwningFileOrUSVString>& aOutValue)
{ {
for (uint32_t i = 0; i < mFormData.Length(); ++i) { for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) { if (aName.Equals(mFormData[i].name)) {
ExtractValue(mFormData[i], &aOutValue.SetValue()); aOutValue.SetValue() = mFormData[i].value;
return; return;
} }
} }
@ -158,7 +149,7 @@ nsFormData::GetAll(const nsAString& aName,
for (uint32_t i = 0; i < mFormData.Length(); ++i) { for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) { if (aName.Equals(mFormData[i].name)) {
OwningFileOrUSVString* element = aValues.AppendElement(); OwningFileOrUSVString* element = aValues.AppendElement();
ExtractValue(mFormData[i], element); *element = mFormData[i].value;
} }
} }
} }
@ -229,6 +220,26 @@ nsFormData::Set(const nsAString& aName, const nsAString& 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 // nsIDOMFormData
@ -297,11 +308,11 @@ nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr); nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
for (uint32_t i = 0; i < mFormData.Length(); ++i) { for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (mFormData[i].valueIsFile) { if (mFormData[i].value.IsFile()) {
fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue); fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile());
} } else {
else { fs.AddNameValuePair(mFormData[i].name,
fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue); mFormData[i].value.GetAsUSVString());
} }
} }

Просмотреть файл

@ -37,13 +37,12 @@ private:
typedef mozilla::dom::Blob Blob; typedef mozilla::dom::Blob Blob;
typedef mozilla::dom::File File; typedef mozilla::dom::File File;
typedef mozilla::dom::OwningFileOrUSVString OwningFileOrUSVString;
struct FormDataTuple struct FormDataTuple
{ {
nsString name; nsString name;
nsString stringValue; OwningFileOrUSVString value;
RefPtr<File> fileValue;
bool valueIsFile;
}; };
// Returns the FormDataTuple to modify. This may be null, in which case // Returns the FormDataTuple to modify. This may be null, in which case
@ -57,8 +56,7 @@ private:
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(aData);
aData->name = aName; aData->name = aName;
aData->stringValue = aValue; aData->value.SetAsUSVString() = aValue;
aData->valueIsFile = false;
} }
void SetNameFilePair(FormDataTuple* aData, void SetNameFilePair(FormDataTuple* aData,
@ -67,12 +65,9 @@ private:
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(aData);
aData->name = aName; aData->name = aName;
aData->fileValue = aFile; aData->value.SetAsFile() = aFile;
aData->valueIsFile = true;
} }
void ExtractValue(const FormDataTuple& aTuple,
mozilla::dom::OwningFileOrUSVString* aOutValue);
public: public:
explicit nsFormData(nsISupports* aOwner = nullptr); explicit nsFormData(nsISupports* aOwner = nullptr);
@ -100,13 +95,17 @@ public:
void Append(const nsAString& aName, Blob& aBlob, void Append(const nsAString& aName, Blob& aBlob,
const mozilla::dom::Optional<nsAString>& aFilename); const mozilla::dom::Optional<nsAString>& aFilename);
void Delete(const nsAString& aName); void Delete(const nsAString& aName);
void Get(const nsAString& aName, mozilla::dom::Nullable<mozilla::dom::OwningFileOrUSVString>& aOutValue); void Get(const nsAString& aName, mozilla::dom::Nullable<OwningFileOrUSVString>& aOutValue);
void GetAll(const nsAString& aName, nsTArray<mozilla::dom::OwningFileOrUSVString>& aValues); void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues);
bool Has(const nsAString& aName); bool Has(const nsAString& aName);
void Set(const nsAString& aName, Blob& aBlob, void Set(const nsAString& aName, Blob& aBlob,
const mozilla::dom::Optional<nsAString>& aFilename); const mozilla::dom::Optional<nsAString>& aFilename);
void Set(const nsAString& aName, const nsAString& aValue); 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 // nsFormSubmission
virtual nsresult GetEncodedSubmission(nsIURI* aURI, virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) override; nsIInputStream** aPostDataStream) override;
@ -120,9 +119,9 @@ public:
virtual nsresult AddNameFilePair(const nsAString& aName, virtual nsresult AddNameFilePair(const nsAString& aName,
File* aFile) override; File* aFile) override;
typedef bool (*FormDataEntryCallback)(const nsString& aName, bool aIsFile, typedef bool (*FormDataEntryCallback)(const nsString& aName,
const nsString& aValue, const OwningFileOrUSVString& aValue,
File* aFile, void* aClosure); void* aClosure);
uint32_t uint32_t
Length() const Length() const
@ -137,8 +136,7 @@ public:
{ {
for (uint32_t i = 0; i < mFormData.Length(); ++i) { for (uint32_t i = 0; i < mFormData.Length(); ++i) {
FormDataTuple& tuple = mFormData[i]; FormDataTuple& tuple = mFormData[i];
if (!aFunc(tuple.name, tuple.valueIsFile, tuple.stringValue, if (!aFunc(tuple.name, tuple.value, aClosure)) {
tuple.fileValue, aClosure)) {
return false; return false;
} }
} }

Просмотреть файл

@ -105,6 +105,56 @@ function testFilename() {
is(f.get("file3").name, "", "File's filename is returned even if empty."); 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) { function testSend(doneCb) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open("POST", "form_submit_server.sjs"); xhr.open("POST", "form_submit_server.sjs");
@ -161,6 +211,7 @@ function runTest(doneCb) {
testSet(); testSet();
testIterate(); testIterate();
testFilename(); testFilename();
testIterable();
// Finally, send an XHR and verify the response matches. // Finally, send an XHR and verify the response matches.
testSend(doneCb); testSend(doneCb);
} }

Просмотреть файл

@ -20,5 +20,5 @@ interface FormData {
boolean has(USVString name); boolean has(USVString name);
void set(USVString name, Blob value, optional USVString filename); void set(USVString name, Blob value, optional USVString filename);
void set(USVString name, USVString value); void set(USVString name, USVString value);
// iterable<USVString, FormDataEntryValue>; - Bug 1127703 iterable<USVString, FormDataEntryValue>;
}; };