mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-26 00:57:30 +09:00
Issue #1442 - Part 23 - Align FetchStream with Firefox 68ESR. https://bugzilla.mozilla.org/show_bug.cgi?id=1612308 https://bugzilla.mozilla.org/show_bug.cgi?id=1445587 Partial part 2 implementing synchronization changes.
This commit is contained in:
parent
41409ab613
commit
836d36dc6d
3 changed files with 139 additions and 32 deletions
|
|
@ -101,6 +101,8 @@ public:
|
||||||
|
|
||||||
virtual void NullifyStream() = 0;
|
virtual void NullifyStream() = 0;
|
||||||
|
|
||||||
|
virtual void MarkAsRead() = 0;
|
||||||
|
|
||||||
virtual JSObject* ReadableStreamBody() = 0;
|
virtual JSObject* ReadableStreamBody() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -237,6 +239,12 @@ public:
|
||||||
return mReadableStreamBody;
|
return mReadableStreamBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkAsRead() override
|
||||||
|
{
|
||||||
|
mBodyUsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual AbortSignal*
|
virtual AbortSignal*
|
||||||
GetSignal() const = 0;
|
GetSignal() const = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "FetchStream.h"
|
#include "FetchStream.h"
|
||||||
|
#include "mozilla/CycleCollectedJSContext.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsNetCID.h"
|
||||||
#include "nsITransport.h"
|
#include "nsITransport.h"
|
||||||
#include "nsIStreamTransportService.h"
|
#include "nsIStreamTransportService.h"
|
||||||
|
|
@ -181,8 +184,12 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
MOZ_DIAGNOSTIC_ASSERT(JS::ReadableStreamIsDisturbed(aStream));
|
MOZ_DIAGNOSTIC_ASSERT(JS::ReadableStreamIsDisturbed(aStream));
|
||||||
|
|
||||||
RefPtr<FetchStream> stream = static_cast<FetchStream*>(aUnderlyingSource);
|
RefPtr<FetchStream> stream = static_cast<FetchStream*>(aUnderlyingSource);
|
||||||
|
stream->AssertIsOnOwningThread();
|
||||||
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(stream->mState == eWaiting ||
|
MutexAutoLock lock(stream->mMutex);
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(stream->mState == eInitializing ||
|
||||||
|
stream->mState == eWaiting ||
|
||||||
stream->mState == eChecking ||
|
stream->mState == eChecking ||
|
||||||
stream->mState == eReading);
|
stream->mState == eReading);
|
||||||
|
|
||||||
|
|
@ -199,6 +206,11 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->mState == eInitializing) {
|
||||||
|
// The stream has been used for the first time.
|
||||||
|
stream->mStreamHolder->MarkAsRead();
|
||||||
|
}
|
||||||
|
|
||||||
stream->mState = eReading;
|
stream->mState = eReading;
|
||||||
|
|
||||||
if (!stream->mInputStream) {
|
if (!stream->mInputStream) {
|
||||||
|
|
@ -209,7 +221,7 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
bool nonBlocking = false;
|
bool nonBlocking = false;
|
||||||
nsresult rv = stream->mOriginalInputStream->IsNonBlocking(&nonBlocking);
|
nsresult rv = stream->mOriginalInputStream->IsNonBlocking(&nonBlocking);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,7 +231,7 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
nsCOMPtr<nsIStreamTransportService> sts =
|
nsCOMPtr<nsIStreamTransportService> sts =
|
||||||
do_GetService(kStreamTransportServiceCID, &rv);
|
do_GetService(kStreamTransportServiceCID, &rv);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +242,7 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
/* aCloseWhenDone */ true,
|
/* aCloseWhenDone */ true,
|
||||||
getter_AddRefs(transport));
|
getter_AddRefs(transport));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +252,7 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
/* aSegmentCount */ 0,
|
/* aSegmentCount */ 0,
|
||||||
getter_AddRefs(wrapper));
|
getter_AddRefs(wrapper));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,7 +269,7 @@ FetchStream::RequestDataCallback(JSContext* aCx,
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
stream->mInputStream->AsyncWait(stream, 0, 0, stream->mOwningEventTarget);
|
stream->mInputStream->AsyncWait(stream, 0, 0, stream->mOwningEventTarget);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,6 +289,9 @@ FetchStream::WriteIntoReadRequestCallback(JSContext* aCx,
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aByteWritten);
|
MOZ_DIAGNOSTIC_ASSERT(aByteWritten);
|
||||||
|
|
||||||
RefPtr<FetchStream> stream = static_cast<FetchStream*>(aUnderlyingSource);
|
RefPtr<FetchStream> stream = static_cast<FetchStream*>(aUnderlyingSource);
|
||||||
|
stream->AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
MutexAutoLock lock(stream->mMutex);
|
||||||
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(stream->mInputStream);
|
MOZ_DIAGNOSTIC_ASSERT(stream->mInputStream);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(stream->mState == eWriting);
|
MOZ_DIAGNOSTIC_ASSERT(stream->mState == eWriting);
|
||||||
|
|
@ -286,20 +301,20 @@ FetchStream::WriteIntoReadRequestCallback(JSContext* aCx,
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
stream->mInputStream->Read(static_cast<char*>(aBuffer), aLength, &written);
|
stream->mInputStream->Read(static_cast<char*>(aBuffer), aLength, &written);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aByteWritten = written;
|
*aByteWritten = written;
|
||||||
|
|
||||||
if (written == 0) {
|
if (written == 0) {
|
||||||
stream->CloseAndReleaseObjects(aCx, aStream);
|
stream->CloseAndReleaseObjects(aCx, lock, aStream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = stream->mInputStream->AsyncWait(stream, 0, 0, stream->mOwningEventTarget);
|
rv = stream->mInputStream->AsyncWait(stream, 0, 0, stream->mOwningEventTarget);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
stream->ErrorPropagation(aCx, aStream, rv);
|
stream->ErrorPropagation(aCx, lock, aStream, rv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -319,6 +334,7 @@ FetchStream::CancelCallback(JSContext* aCx, JS::HandleObject aStream,
|
||||||
// We are guaranteed that won't happen until the js ReadableStream object
|
// We are guaranteed that won't happen until the js ReadableStream object
|
||||||
// is finalized.
|
// is finalized.
|
||||||
FetchStream* stream = static_cast<FetchStream*>(aUnderlyingSource);
|
FetchStream* stream = static_cast<FetchStream*>(aUnderlyingSource);
|
||||||
|
stream->AssertIsOnOwningThread();
|
||||||
|
|
||||||
if (stream->mInputStream) {
|
if (stream->mInputStream) {
|
||||||
stream->mInputStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
stream->mInputStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
||||||
|
|
@ -344,6 +360,24 @@ FetchStream::ErroredCallback(JSContext* aCx, JS::HandleObject aStream,
|
||||||
{
|
{
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aUnderlyingSource);
|
MOZ_DIAGNOSTIC_ASSERT(aUnderlyingSource);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aFlags == FETCH_STREAM_FLAG);
|
MOZ_DIAGNOSTIC_ASSERT(aFlags == FETCH_STREAM_FLAG);
|
||||||
|
|
||||||
|
// This is safe because we created an extra reference in FetchStream::Create()
|
||||||
|
// that won't be released until FetchStream::FinalizeCallback() is called.
|
||||||
|
// We are guaranteed that won't happen until the js ReadableStream object
|
||||||
|
// is finalized.
|
||||||
|
FetchStream* stream = static_cast<FetchStream*>(aUnderlyingSource);
|
||||||
|
stream->AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
if (stream->mState == eInitializing) {
|
||||||
|
// The stream has been used for the first time.
|
||||||
|
stream->mStreamHolder->MarkAsRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->mInputStream) {
|
||||||
|
stream->mInputStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->ReleaseObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -364,7 +398,8 @@ FetchStream::FinalizeCallback(void* aUnderlyingSource, uint8_t aFlags)
|
||||||
FetchStream::FetchStream(nsIGlobalObject* aGlobal,
|
FetchStream::FetchStream(nsIGlobalObject* aGlobal,
|
||||||
FetchStreamHolder* aStreamHolder,
|
FetchStreamHolder* aStreamHolder,
|
||||||
nsIInputStream* aInputStream)
|
nsIInputStream* aInputStream)
|
||||||
: mState(eWaiting)
|
: mMutex("FetchStream::mMutex")
|
||||||
|
, mState(eInitializing)
|
||||||
, mGlobal(aGlobal)
|
, mGlobal(aGlobal)
|
||||||
, mStreamHolder(aStreamHolder)
|
, mStreamHolder(aStreamHolder)
|
||||||
, mOriginalInputStream(aInputStream)
|
, mOriginalInputStream(aInputStream)
|
||||||
|
|
@ -379,9 +414,13 @@ FetchStream::~FetchStream()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FetchStream::ErrorPropagation(JSContext* aCx, JS::HandleObject aStream,
|
FetchStream::ErrorPropagation(JSContext* aCx,
|
||||||
|
const MutexAutoLock& aProofOfLock,
|
||||||
|
JS::HandleObject aStream,
|
||||||
nsresult aError)
|
nsresult aError)
|
||||||
{
|
{
|
||||||
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
if (mState == eClosed) {
|
if (mState == eClosed) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -389,7 +428,7 @@ FetchStream::ErrorPropagation(JSContext* aCx, JS::HandleObject aStream,
|
||||||
|
|
||||||
// Let's close the stream.
|
// Let's close the stream.
|
||||||
if (aError == NS_BASE_STREAM_CLOSED) {
|
if (aError == NS_BASE_STREAM_CLOSED) {
|
||||||
CloseAndReleaseObjects(aCx, aStream);
|
CloseAndReleaseObjects(aCx, aProofOfLock, aStream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,31 +439,34 @@ FetchStream::ErrorPropagation(JSContext* aCx, JS::HandleObject aStream,
|
||||||
|
|
||||||
JS::Rooted<JS::Value> errorValue(aCx);
|
JS::Rooted<JS::Value> errorValue(aCx);
|
||||||
if (ToJSValue(aCx, error, &errorValue)) {
|
if (ToJSValue(aCx, error, &errorValue)) {
|
||||||
|
MutexAutoUnlock unlock(mMutex);
|
||||||
JS::ReadableStreamError(aCx, aStream, errorValue);
|
JS::ReadableStreamError(aCx, aStream, errorValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReleaseObjects(aProofOfLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
FetchStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
FetchStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||||
{
|
{
|
||||||
|
AssertIsOnOwningThread();
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aStream);
|
MOZ_DIAGNOSTIC_ASSERT(aStream);
|
||||||
|
|
||||||
|
Maybe<MutexAutoLock> lock;
|
||||||
|
lock.emplace(mMutex);
|
||||||
|
|
||||||
// Already closed. We have nothing else to do here.
|
// Already closed. We have nothing else to do here.
|
||||||
if (mState == eClosed) {
|
if (mState == eClosed) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoMicroTask mt;
|
||||||
|
AutoEntryScript aes(mGlobal, "fetch body data available");
|
||||||
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mInputStream);
|
MOZ_DIAGNOSTIC_ASSERT(mInputStream);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mState == eReading || mState == eChecking);
|
MOZ_DIAGNOSTIC_ASSERT(mState == eReading || mState == eChecking);
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
JSContext* cx = aes.cx();
|
||||||
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
|
|
||||||
// Without JSContext we are not able to close the stream or to propagate the
|
|
||||||
// error.
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSContext* cx = jsapi.cx();
|
|
||||||
JS::Rooted<JSObject*> stream(cx, mStreamHolder->ReadableStreamBody());
|
JS::Rooted<JSObject*> stream(cx, mStreamHolder->ReadableStreamBody());
|
||||||
|
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
|
|
@ -437,7 +479,7 @@ FetchStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||||
|
|
||||||
// No warning for stream closed.
|
// No warning for stream closed.
|
||||||
if (rv == NS_BASE_STREAM_CLOSED || NS_WARN_IF(NS_FAILED(rv))) {
|
if (rv == NS_BASE_STREAM_CLOSED || NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
ErrorPropagation(cx, stream, rv);
|
ErrorPropagation(cx, *lock, stream, rv);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -448,10 +490,10 @@ FetchStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
mState = eWriting;
|
mState = eWriting;
|
||||||
JS::ReadableStreamUpdateDataAvailableFromSource(cx, stream, size);
|
|
||||||
|
|
||||||
// The WriteInto callback changes mState to eChecking.
|
lock.reset();
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mState == eChecking);
|
|
||||||
|
JS::ReadableStreamUpdateDataAvailableFromSource(cx, stream, size);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -465,6 +507,7 @@ FetchStream::RetrieveInputStream(void* aUnderlyingReadableStreamSource,
|
||||||
|
|
||||||
RefPtr<FetchStream> stream =
|
RefPtr<FetchStream> stream =
|
||||||
static_cast<FetchStream*>(aUnderlyingReadableStreamSource);
|
static_cast<FetchStream*>(aUnderlyingReadableStreamSource);
|
||||||
|
stream->AssertIsOnOwningThread();
|
||||||
|
|
||||||
// if mOriginalInputStream is null, the reading already started. We don't want
|
// if mOriginalInputStream is null, the reading already started. We don't want
|
||||||
// to expose the internal inputStream.
|
// to expose the internal inputStream.
|
||||||
|
|
@ -480,28 +523,37 @@ FetchStream::RetrieveInputStream(void* aUnderlyingReadableStreamSource,
|
||||||
void
|
void
|
||||||
FetchStream::Close()
|
FetchStream::Close()
|
||||||
{
|
{
|
||||||
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
if (mState == eClosed) {
|
if (mState == eClosed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
|
if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
|
||||||
ReleaseObjects();
|
ReleaseObjects(lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSContext* cx = jsapi.cx();
|
JSContext* cx = jsapi.cx();
|
||||||
JS::Rooted<JSObject*> stream(cx, mStreamHolder->ReadableStreamBody());
|
JS::Rooted<JSObject*> stream(cx, mStreamHolder->ReadableStreamBody());
|
||||||
|
|
||||||
CloseAndReleaseObjects(cx, stream);
|
CloseAndReleaseObjects(cx, lock, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FetchStream::CloseAndReleaseObjects(JSContext* aCx, JS::HandleObject aStream)
|
FetchStream::CloseAndReleaseObjects(JSContext* aCx,
|
||||||
|
const MutexAutoLock& aProofOfLock,
|
||||||
|
JS::HandleObject aStream)
|
||||||
{
|
{
|
||||||
|
AssertIsOnOwningThread();
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mState != eClosed);
|
MOZ_DIAGNOSTIC_ASSERT(mState != eClosed);
|
||||||
|
|
||||||
ReleaseObjects();
|
ReleaseObjects(aProofOfLock);
|
||||||
|
|
||||||
|
MutexAutoUnlock unlock(mMutex);
|
||||||
|
|
||||||
if (JS::ReadableStreamIsReadable(aStream)) {
|
if (JS::ReadableStreamIsReadable(aStream)) {
|
||||||
JS::ReadableStreamClose(aCx, aStream);
|
JS::ReadableStreamClose(aCx, aStream);
|
||||||
|
|
@ -511,7 +563,20 @@ FetchStream::CloseAndReleaseObjects(JSContext* aCx, JS::HandleObject aStream)
|
||||||
void
|
void
|
||||||
FetchStream::ReleaseObjects()
|
FetchStream::ReleaseObjects()
|
||||||
{
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
ReleaseObjects(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FetchStream::ReleaseObjects(const MutexAutoLock& aProofOfLock)
|
||||||
|
{
|
||||||
|
// This method can be called on 2 possible threads: the owning one and a JS
|
||||||
|
// thread used to release resources. If we are on the JS thread, we need to
|
||||||
|
// dispatch a runnable to go back to the owning thread in order to release
|
||||||
|
// resources correctly.
|
||||||
|
|
||||||
if (mState == eClosed) {
|
if (mState == eClosed) {
|
||||||
|
// Already gone. Nothing to do.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,6 +606,14 @@ FetchStream::ReleaseObjects()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void
|
||||||
|
FetchStream::AssertIsOnOwningThread()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(FetchStream);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// nsIObserver
|
// nsIObserver
|
||||||
// -----------
|
// -----------
|
||||||
|
|
||||||
|
|
@ -549,6 +622,7 @@ FetchStream::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
const char16_t* aData)
|
const char16_t* aData)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
MOZ_ASSERT(strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0);
|
MOZ_ASSERT(strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@ private:
|
||||||
nsIInputStream* aInputStream);
|
nsIInputStream* aInputStream);
|
||||||
~FetchStream();
|
~FetchStream();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void
|
||||||
|
AssertIsOnOwningThread();
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
AssertIsOnOwningThread() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RequestDataCallback(JSContext* aCx, JS::HandleObject aStream,
|
RequestDataCallback(JSContext* aCx, JS::HandleObject aStream,
|
||||||
void* aUnderlyingSource, uint8_t aFlags,
|
void* aUnderlyingSource, uint8_t aFlags,
|
||||||
|
|
@ -81,10 +89,19 @@ private:
|
||||||
FinalizeCallback(void* aUnderlyingSource, uint8_t aFlags);
|
FinalizeCallback(void* aUnderlyingSource, uint8_t aFlags);
|
||||||
|
|
||||||
void
|
void
|
||||||
ErrorPropagation(JSContext* aCx, JS::HandleObject aStream, nsresult aRv);
|
ErrorPropagation(JSContext* aCx,
|
||||||
|
const MutexAutoLock& aProofOfLock,
|
||||||
|
JS::HandleObject aStream, nsresult aRv);
|
||||||
|
|
||||||
void
|
void
|
||||||
CloseAndReleaseObjects(JSContext* aCx, JS::HandleObject aStream);
|
CloseAndReleaseObjects(JSContext* aCx,
|
||||||
|
const MutexAutoLock& aProofOfLock,
|
||||||
|
JS::HandleObject aSteam);
|
||||||
|
|
||||||
|
class WorkerShutdown;
|
||||||
|
|
||||||
|
void
|
||||||
|
ReleaseObjects(const MutexAutoLock& aProofOfLock);
|
||||||
|
|
||||||
void
|
void
|
||||||
ReleaseObjects();
|
ReleaseObjects();
|
||||||
|
|
@ -92,6 +109,9 @@ private:
|
||||||
// Common methods
|
// Common methods
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
|
// This is the beginning state before any reading operation.
|
||||||
|
eInitializing,
|
||||||
|
|
||||||
// RequestDataCallback has not been called yet. We haven't started to read
|
// RequestDataCallback has not been called yet. We haven't started to read
|
||||||
// data from the stream yet.
|
// data from the stream yet.
|
||||||
eWaiting,
|
eWaiting,
|
||||||
|
|
@ -111,7 +131,12 @@ private:
|
||||||
eClosed,
|
eClosed,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Touched only on the target thread.
|
// We need a mutex because JS engine can release FetchStream on a non-owning
|
||||||
|
// thread. We must be sure that the releasing of resources doesn't trigger
|
||||||
|
// race conditions.
|
||||||
|
Mutex mMutex;
|
||||||
|
|
||||||
|
// Protected by mutex.
|
||||||
State mState;
|
State mState;
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue