зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1127703 - Support iteration on FormData, r=bz
This commit is contained in:
Родитель
cc10dd7ad3
Коммит
c628603a97
|
@ -862,16 +862,16 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
|
|||
{ }
|
||||
|
||||
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;
|
||||
|
@ -882,9 +882,10 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,9 @@ 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);
|
||||
if (tmp->mFormData[i].value.IsFile()) {
|
||||
ImplCycleCollectionUnlink(tmp->mFormData[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
|
@ -71,8 +73,8 @@ 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
|
||||
|
@ -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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +149,7 @@ nsFormData::GetAll(const nsAString& aName,
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -297,11 +308,11 @@ nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
|||
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 {
|
||||
fs.AddNameValuePair(mFormData[i].name,
|
||||
mFormData[i].value.GetAsUSVString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,12 @@ private:
|
|||
|
||||
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
|
||||
|
@ -57,8 +56,7 @@ private:
|
|||
{
|
||||
MOZ_ASSERT(aData);
|
||||
aData->name = aName;
|
||||
aData->stringValue = aValue;
|
||||
aData->valueIsFile = false;
|
||||
aData->value.SetAsUSVString() = aValue;
|
||||
}
|
||||
|
||||
void SetNameFilePair(FormDataTuple* aData,
|
||||
|
@ -67,12 +65,9 @@ private:
|
|||
{
|
||||
MOZ_ASSERT(aData);
|
||||
aData->name = aName;
|
||||
aData->fileValue = aFile;
|
||||
aData->valueIsFile = true;
|
||||
aData->value.SetAsFile() = aFile;
|
||||
}
|
||||
|
||||
void ExtractValue(const FormDataTuple& aTuple,
|
||||
mozilla::dom::OwningFileOrUSVString* aOutValue);
|
||||
public:
|
||||
explicit nsFormData(nsISupports* aOwner = nullptr);
|
||||
|
||||
|
@ -100,13 +95,17 @@ public:
|
|||
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;
|
||||
|
@ -120,9 +119,9 @@ public:
|
|||
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
|
||||
|
@ -137,8 +136,7 @@ public:
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,56 @@ function testFilename() {
|
|||
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");
|
||||
|
@ -161,6 +211,7 @@ function runTest(doneCb) {
|
|||
testSet();
|
||||
testIterate();
|
||||
testFilename();
|
||||
testIterable();
|
||||
// Finally, send an XHR and verify the response matches.
|
||||
testSend(doneCb);
|
||||
}
|
||||
|
|
|
@ -20,5 +20,5 @@ interface FormData {
|
|||
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>;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче