Bug 649672: Make File.slice arguments match Array.slice and prefix File.slice. r=khuey

This commit is contained in:
Jonas Sicking 2011-04-13 14:34:36 -07:00
Родитель 6e8a05de6b
Коммит 3815106388
5 изменённых файлов: 150 добавлений и 113 удалений

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

@ -57,6 +57,7 @@ class nsIInputStream;
class nsIClassInfo;
class nsDOMFile : public nsIDOMFile,
public nsIDOMBlob_MOZILLA_2_0_BRANCH,
public nsIXHRSendable,
public nsICharsetDetectionObserver
{
@ -64,6 +65,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLOB
NS_DECL_NSIDOMFILE
NS_DECL_NSIDOMBLOB_MOZILLA_2_0_BRANCH
NS_DECL_NSIXHRSENDABLE
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)
@ -149,8 +151,9 @@ public:
NS_IMETHOD GetSize(PRUint64*);
NS_IMETHOD GetInternalStream(nsIInputStream**);
NS_IMETHOD GetMozFullPathInternal(nsAString&);
NS_IMETHOD Slice(PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType, nsIDOMBlob **aBlob);
NS_IMETHOD MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
nsIDOMBlob **aBlob);
protected:
friend class DataOwnerAdapter; // Needs to see DataOwner

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

@ -49,9 +49,9 @@ interface nsIDOMBlob : nsISupports
readonly attribute unsigned long long size;
readonly attribute DOMString type;
nsIDOMBlob slice(in unsigned long long start,
in unsigned long long length,
[optional] in DOMString contentType);
[noscript] nsIDOMBlob slice(in unsigned long long start,
in unsigned long long length,
[optional] in DOMString contentType);
[noscript] readonly attribute nsIInputStream internalStream;
// The caller is responsible for releasing the internalUrl from the
@ -59,6 +59,14 @@ interface nsIDOMBlob : nsISupports
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
};
[scriptable, uuid(cb5b4191-a555-4e57-b8d2-88091184b59f)]
interface nsIDOMBlob_MOZILLA_2_0_BRANCH : nsISupports
{
[optional_argc] nsIDOMBlob mozSlice(in long long start,
[optional] in long long end,
[optional] in DOMString contentType);
};
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)]
interface nsIDOMFile : nsIDOMBlob
{

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

@ -139,6 +139,7 @@ DOMCI_DATA(Blob, nsDOMFile)
NS_INTERFACE_MAP_BEGIN(nsDOMFile)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
@ -245,23 +246,54 @@ nsDOMFile::GetType(nsAString &aType)
return NS_OK;
}
// Makes sure that aStart and aStart + aLength is less then or equal to aSize
// Makes sure that aStart and aEnd is less then or equal to aSize and greater
// than 0
void
ClampToSize(PRUint64 aSize, PRUint64& aStart, PRUint64& aLength)
ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
{
if (aStart > aSize) {
aStart = aLength = 0;
CheckedInt64 newStartOffset = aStart;
if (aStart < -aSize) {
newStartOffset = 0;
}
CheckedUint64 endOffset = aStart;
endOffset += aLength;
if (!endOffset.valid() || endOffset.value() > aSize) {
aLength = aSize - aStart;
else if (aStart < 0) {
newStartOffset += aSize;
}
else if (aStart > aSize) {
newStartOffset = aSize;
}
CheckedInt64 newEndOffset = aEnd;
if (aEnd < -aSize) {
newEndOffset = 0;
}
else if (aEnd < 0) {
newEndOffset += aSize;
}
else if (aEnd > aSize) {
newEndOffset = aSize;
}
if (!newStartOffset.valid() || !newEndOffset.valid() ||
newStartOffset.value() >= newEndOffset.value()) {
aStart = aEnd = 0;
}
else {
aStart = newStartOffset.value();
aEnd = newEndOffset.value();
}
}
NS_IMETHODIMP
nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType, nsIDOMBlob **aBlob)
{
return MozSlice(aStart, aStart + aLength, aContentType, 2, aBlob);
}
NS_IMETHODIMP
nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
nsIDOMBlob **aBlob)
{
*aBlob = nsnull;
@ -269,10 +301,15 @@ nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
PRUint64 thisLength;
nsresult rv = GetSize(&thisLength);
NS_ENSURE_SUCCESS(rv, rv);
ClampToSize(thisLength, aStart, aLength);
if (!optional_argc) {
aEnd = (PRInt64)thisLength;
}
ParseSize((PRInt64)thisLength, aStart, aEnd);
// Create the new file
NS_ADDREF(*aBlob = new nsDOMFile(this, aStart, aLength, aContentType));
NS_ADDREF(*aBlob = new nsDOMFile(this, aStart, aEnd - aStart, aContentType));
return NS_OK;
}
@ -627,16 +664,22 @@ nsDOMMemoryFile::GetSize(PRUint64 *aFileSize)
}
NS_IMETHODIMP
nsDOMMemoryFile::Slice(PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType, nsIDOMBlob **aBlob)
nsDOMMemoryFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
nsIDOMBlob **aBlob)
{
*aBlob = nsnull;
if (!optional_argc) {
aEnd = (PRInt64)mLength;
}
// Truncate aLength and aStart so that we stay within this file.
ClampToSize(mLength, aStart, aLength);
ParseSize((PRInt64)mLength, aStart, aEnd);
// Create the new file
NS_ADDREF(*aBlob = new nsDOMMemoryFile(this, aStart, aLength, aContentType));
NS_ADDREF(*aBlob = new nsDOMMemoryFile(this, aStart, aEnd - aStart,
aContentType));
return NS_OK;
}

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

@ -69,104 +69,83 @@ ok(size > 65536, "test data sufficiently large");
// Test that basic properties work
function testBasics(file, size, type) {
is(file.type, type, "[B0] mozGetAsFile type");
is(file.size, size, "[B0] file is correct size");
ok(file instanceof File, "[B0] file is a File");
ok(file instanceof Blob, "[B0] file is also a Blob");
function testFile(file, size, type, contents, fileType) {
is(file.type, type, fileType + " file is correct type");
is(file.size, size, fileType + " file is correct size");
ok(file instanceof File, fileType + " file is a File");
ok(file instanceof Blob, fileType + " file is also a Blob");
var slice = file.slice(0, size);
is(slice.type, "", "[B1] full-size type");
is(slice.size, size, "[B1] full-size size");
ok(slice instanceof Blob, "[B1] slice is a Blob");
ok(!(slice instanceof File), "[B1] slice is not a File");
var slice = file.mozSlice(0, size);
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
slice = file.slice(0, 1234);
is(slice.type, "", "[B2] sized type");
is(slice.size, 1234, "[B2] sized size");
ok(slice instanceof Blob, "[B2] slice is a Blob");
ok(!(slice instanceof File), "[B2] slice is not a File");
slice = file.mozSlice(0, 1234);
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
ok(!(slice instanceof File), fileType + " sized slice is not a File");
slice = file.slice(size-500, 1000);
is(slice.type, "", "[B3] end-sized type");
is(slice.size, 500, "[B3] end-sized size");
slice = file.slice(size+500, 1000);
is(slice.type, "", "[B4] sized type");
is(slice.size, 0, "[B4] sized size");
slice = file.mozSlice(0, size, "foo/bar");
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
slice = file.slice(0, 0);
is(slice.type, "", "[B5] sized type");
is(slice.size, 0, "[B5] sized size");
slice = file.slice(1000, 0);
is(slice.type, "", "[B6] sized type");
is(slice.size, 0, "[B6] sized size");
slice = file.mozSlice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
slice = file.slice(0, size, "foo/bar");
is(slice.type, "foo/bar", "[B7] full-size foo/bar type");
is(slice.size, size, "[B7] full-size foo/bar size");
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
slice = file.slice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", "[B8] sized foo/bar type");
is(slice.size, 5432, "[B8] sized foo/bar size");
var indexes = [[0, size, size],
[0, 1234, 1234],
[size-500, size, 500],
[size-500, size+500, 500],
[size+500, size+1500, 0],
[0, 0, 0],
[1000, 1000, 0],
[size, size, 0],
[0, undefined, size],
[100, undefined, size-100],
[-100, undefined, 100],
[100, -100, size-200],
[-size-100, undefined, size],
[-2*size-100, 500, 500],
[0, -size-100, 0],
[100, -size-100, 0],
[50, -size+100, 50],
[0, 33000, 33000],
[1000, 34000, 33000],
];
is(slice.slice(0, 10).type, "", "[B9] slice-slice type");
is(slice.slice(0, 10).size, 10, "[B9] slice-slice size");
is(slice.slice(0, 10, "hello/world").type, "hello/world", "[B9] slice-slice hello/world type");
is(slice.slice(0, 10, "hello/world").size, 10, "[B9] slice-slice hello/world type");
for (var i = 0; i < indexes.length; ++i) {
var sliceContents;
var testName;
if (indexes[i][1] == undefined) {
slice = file.mozSlice(indexes[i][0]);
sliceContents = contents.slice(indexes[i][0]);
testName = fileType + " slice(" + indexes[i][0] + ")";
}
else {
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
}
is(slice.type, "", testName + " type");
is(slice.size, indexes[i][2], testName + " size");
is(sliceContents.length, indexes[i][2], testName + " data size");
checkFileContents(slice, sliceContents, testName);
}
// Slice of slice
var slice = file.mozSlice(0, 40000);
checkFileContents(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
// ...of slice of slice
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
gc();
checkFileContents(slice, contents.slice(5400, 5700), "file slice slice slice");
}
testBasics(memFile, size, "image/png");
testBasics(fileFile, size, "");
// Test reading various slices
// Full file
testFile(memFile, fileData, "mem file");
testFile(fileFile, fileData, "file file");
// Simple slice
testFile(memFile.slice(0, 33000), fileData.substr(0, 33000), "mem file slice");
testFile(fileFile.slice(0, 33000), fileData.substr(0, 33000), "file file slice");
// Simple slice not starting at beginning
testFile(memFile.slice(1000, 33000), fileData.substr(1000, 33000), "mem file slice starting at non-zero");
testFile(fileFile.slice(1000, 33000), fileData.substr(1000, 33000), "file file slice starting at non-zero");
// Slice of slice
var memSlice = memFile.slice(0, 40000);
var fileSlice = fileFile.slice(0, 40000);
testFile(memSlice.slice(5000, 37000), fileData.substr(5000, 35000), "mem file slice slice");
testFile(fileSlice.slice(5000, 37000), fileData.substr(5000, 35000), "file file slice slice");
// ...of slice of slice
memSlice = memSlice.slice(5000, 37000).slice(400, 300);
fileSlice = fileSlice.slice(5000, 37000).slice(400, 300);
gc();
testFile(memSlice, fileData.substr(5400, 300), "mem file slice slice slice");
testFile(fileSlice, fileData.substr(5400, 300), "file file slice slice slice");
// empty slice
testFile(memFile.slice(4711, 0), "", "mem file empty slice (1)");
testFile(fileFile.slice(4711, 0), "", "file file empty slice (1)");
testFile(memFile.slice(0, 0), "", "mem file empty slice (2)");
testFile(fileFile.slice(0, 0), "", "file file empty slice (2)");
// slice at end
testFile(memFile.slice(size-1000, 1000), fileData.substr(size-1000, 1000), "mem file slice at end");
testFile(fileFile.slice(size-1000, 1000), fileData.substr(size-1000, 1000), "file file slice at end");
// slice across end
testFile(memFile.slice(size-500, 1000), fileData.substr(size-500, 500), "mem file slice across end");
testFile(fileFile.slice(size-500, 1000), fileData.substr(size-500, 500), "file file slice across end");
// slice past end
testFile(memFile.slice(size, 1000), "", "mem file slice past end (1)");
testFile(fileFile.slice(size, 1000), "", "file file slice past end (1)");
testFile(memFile.slice(size + 1000, 1000), "", "mem file slice past end (2)");
testFile(fileFile.slice(size + 1000, 1000), "", "file file slice past end (2)");
testFile(memFile, size, "image/png", fileData, "memFile");
testFile(fileFile, size, "", fileData, "fileFile");
// Try loading directly from slice into an image
@ -202,7 +181,7 @@ function imageLoadHandler(event) {
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
var img = new Image;
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size));
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
img.onload = imageLoadHandler;
expectedTestCount++;
@ -210,7 +189,7 @@ expectedTestCount++;
var imgfile = createFileWithData(fileData + testBinaryData);
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
var img = new Image;
img.src = URL.createObjectURL(imgfile.slice(0, size));
img.src = URL.createObjectURL(imgfile.mozSlice(0, size));
img.onload = imageLoadHandler;
expectedTestCount++;
@ -218,7 +197,7 @@ expectedTestCount++;
var imgfile = createFileWithData(testBinaryData + fileData);
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
var img = new Image;
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size));
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
img.onload = imageLoadHandler;
expectedTestCount++;
@ -226,13 +205,15 @@ expectedTestCount++;
var imgfile = createFileWithData(testBinaryData + fileData);
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
var img = new Image;
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size + 1000));
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size + 1000));
img.onload = imageLoadHandler;
expectedTestCount++;
// Utility functions
function testFile(file, contents, test) {
function checkFileContents(file, contents, test) {
SimpleTest.requestLongerTimeout(2);
// Load file using FileReader
var r = new FileReader();
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);

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

@ -3911,10 +3911,12 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
DOM_CLASSINFO_MAP_END