Bug 1502403 - FileReader should dispatch loadstart asynchronously, r=smaug,ssengupta

Differential Revision: https://phabricator.services.mozilla.com/D78852
This commit is contained in:
Andrea Marchesini 2020-06-09 14:41:14 +00:00
parent 2ff52580c4
commit b058e12e25
6 changed files with 71 additions and 41 deletions

View File

@ -84,6 +84,28 @@ class MOZ_RAII FileReaderDecreaseBusyCounter {
~FileReaderDecreaseBusyCounter() { mFileReader->DecreaseBusyCounter(); }
};
class FileReader::AsyncWaitRunnable final : public CancelableRunnable {
public:
explicit AsyncWaitRunnable(FileReader* aReader)
: CancelableRunnable("FileReader::AsyncWaitRunnable"), mReader(aReader) {}
NS_IMETHOD
Run() override {
if (mReader) {
mReader->InitialAsyncWait();
}
return NS_OK;
}
nsresult Cancel() override {
mReader = nullptr;
return NS_OK;
}
public:
RefPtr<FileReader> mReader;
};
void FileReader::RootResultArrayBuffer() { mozilla::HoldJSObjects(this); }
// FileReader constructors/initializers
@ -156,7 +178,7 @@ void FileReader::GetResult(JSContext* aCx,
return;
}
if (mResult.IsVoid()) {
if (mReadyState != DONE || mResult.IsVoid()) {
aResult.SetNull();
return;
}
@ -400,7 +422,8 @@ void FileReader::ReadFileContent(Blob& aBlob, const nsAString& aCharset,
}
}
aRv = DoAsyncWait();
mAsyncWaitRunnable = new AsyncWaitRunnable(this);
aRv = NS_DispatchToCurrentThread(mAsyncWaitRunnable);
if (NS_WARN_IF(aRv.Failed())) {
FreeFileData();
return;
@ -408,6 +431,18 @@ void FileReader::ReadFileContent(Blob& aBlob, const nsAString& aCharset,
// FileReader should be in loading state here
mReadyState = LOADING;
}
void FileReader::InitialAsyncWait() {
mAsyncWaitRunnable = nullptr;
nsresult rv = DoAsyncWait();
if (NS_WARN_IF(NS_FAILED(rv))) {
mReadyState = EMPTY;
FreeFileData();
return;
}
DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
}
@ -694,6 +729,11 @@ void FileReader::Abort() {
ClearProgressEventTimer();
if (mAsyncWaitRunnable) {
mAsyncWaitRunnable->Cancel();
mAsyncWaitRunnable = nullptr;
}
mReadyState = DONE;
// XXX The spec doesn't say this
@ -703,6 +743,20 @@ void FileReader::Abort() {
SetDOMStringToNull(mResult);
mResultArrayBuffer = nullptr;
// If we have the stream and the busy-count is not 0, it means that we are
// waiting for an OnInputStreamReady() call. Let's abort the current
// AsyncWait() calling it again with a nullptr callback. See
// nsIAsyncInputStream.idl.
if (mAsyncStream && mBusyCount) {
mAsyncStream->AsyncWait(/* callback */ nullptr,
/* aFlags*/ 0,
/* aRequestedCount */ 0, mTarget);
DecreaseBusyCounter();
MOZ_ASSERT(mBusyCount == 0);
mAsyncStream->Close();
}
mAsyncStream = nullptr;
mBlob = nullptr;
@ -712,7 +766,7 @@ void FileReader::Abort() {
// Dispatch the events
DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
}
} // namespace dom
nsresult FileReader::IncreaseBusyCounter() {
if (mWeakWorkerRef && mBusyCount++ == 0) {
@ -745,6 +799,11 @@ void FileReader::DecreaseBusyCounter() {
void FileReader::Shutdown() {
mReadyState = DONE;
if (mAsyncWaitRunnable) {
mAsyncWaitRunnable->Cancel();
mAsyncWaitRunnable = nullptr;
}
if (mAsyncStream) {
mAsyncStream->Close();
mAsyncStream = nullptr;

View File

@ -117,6 +117,8 @@ class FileReader final : public DOMEventTargetHelper,
eDataFormat DataFormat() const { return mDataFormat; }
const nsString& Result() const { return mResult; }
void InitialAsyncWait();
private:
virtual ~FileReader();
@ -191,6 +193,10 @@ class FileReader final : public DOMEventTargetHelper,
// This value is set when the reading starts in order to keep the worker alive
// during the process.
RefPtr<StrongWorkerRef> mStrongWorkerRef;
// Runnable to start the reading asynchronous.
class AsyncWaitRunnable;
RefPtr<AsyncWaitRunnable> mAsyncWaitRunnable;
};
NS_DEFINE_STATIC_IID_ACCESSOR(FileReader, FILEREADER_ID)

View File

@ -344,7 +344,7 @@ function test_readAsText(blob, text) {
is(r.readyState, FileReader.LOADING, "correct loading text readyState");
is(onloadHasRun, false, "text loading must be async");
is(onloadStartHasRun, true, "text loadstart should fire sync");
is(onloadStartHasRun, false, "text loadstart should fire async");
});
}
@ -378,7 +378,7 @@ function test_readAsBinaryString(blob, text) {
is(r.readyState, FileReader.LOADING, "correct loading binary readyState");
is(onloadHasRun, false, "binary loading must be async");
is(onloadStartHasRun, true, "binary loadstart should fire sync");
is(onloadStartHasRun, false, "binary loadstart should fire async");
});
}
@ -419,7 +419,7 @@ function test_readAsArrayBuffer(blob, text) {
"correct loading arrayBuffer readyState"
);
is(onloadHasRun, false, "arrayBuffer loading must be async");
is(onloadStartHasRun, true, "arrayBuffer loadstart should fire sync");
is(onloadStartHasRun, false, "arrayBuffer loadstart should fire sync");
});
}

View File

@ -1,4 +0,0 @@
[filereader_abort.html]
[Aborting after read]
expected: FAIL

View File

@ -1,15 +0,0 @@
[filereader_events.any.html]
[events are dispatched in the correct order for a non-empty blob]
expected: FAIL
[events are dispatched in the correct order for an empty blob]
expected: FAIL
[filereader_events.any.worker.html]
[events are dispatched in the correct order for a non-empty blob]
expected: FAIL
[events are dispatched in the correct order for an empty blob]
expected: FAIL

View File

@ -1,16 +0,0 @@
[filereader_result.html]
[result is null during "loadstart" event for readAsBinaryString]
expected: FAIL
[result is null during "loadstart" event for readAsDataURL]
expected: FAIL
[result is null during "progress" event for readAsBinaryString]
expected: FAIL
[result is null during "loadstart" event for readAsArrayBuffer]
expected: FAIL
[result is null during "loadstart" event for readAsText]
expected: FAIL