зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1311466 - Part 8: Implement basic functionality for preprocessing results before they are sent for synchronous deserialization; r=asuth
This commit is contained in:
Родитель
828a986c64
Коммит
9d0d2c5654
|
@ -34,6 +34,8 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
@ -590,22 +592,23 @@ protected:
|
|||
|
||||
void
|
||||
DeserializeStructuredCloneFiles(
|
||||
IDBDatabase* aDatabase,
|
||||
const SerializedStructuredCloneReadInfo& aCloneReadInfo,
|
||||
nsTArray<StructuredCloneFile>& aFiles)
|
||||
IDBDatabase* aDatabase,
|
||||
const nsTArray<SerializedStructuredCloneFile>& aSerializedFiles,
|
||||
const nsTArray<RefPtr<JS::WasmModule>>* aModules,
|
||||
nsTArray<StructuredCloneFile>& aFiles)
|
||||
{
|
||||
MOZ_ASSERT_IF(aModules, !aModules->IsEmpty());
|
||||
MOZ_ASSERT(aFiles.IsEmpty());
|
||||
|
||||
const nsTArray<SerializedStructuredCloneFile>& serializedFiles =
|
||||
aCloneReadInfo.files();
|
||||
if (!aSerializedFiles.IsEmpty()) {
|
||||
uint32_t moduleIndex = 0;
|
||||
|
||||
if (!serializedFiles.IsEmpty()) {
|
||||
const uint32_t count = serializedFiles.Length();
|
||||
const uint32_t count = aSerializedFiles.Length();
|
||||
aFiles.SetCapacity(count);
|
||||
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
const SerializedStructuredCloneFile& serializedFile =
|
||||
serializedFiles[index];
|
||||
aSerializedFiles[index];
|
||||
|
||||
const BlobOrMutableFile& blobOrMutableFile = serializedFile.file();
|
||||
|
||||
|
@ -687,6 +690,20 @@ DeserializeStructuredCloneFiles(
|
|||
}
|
||||
|
||||
case StructuredCloneFile::eWasmBytecode: {
|
||||
if (aModules) {
|
||||
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
|
||||
|
||||
StructuredCloneFile* file = aFiles.AppendElement();
|
||||
MOZ_ASSERT(file);
|
||||
|
||||
file->mType = serializedFile.type();
|
||||
|
||||
MOZ_ASSERT(moduleIndex < aModules->Length());
|
||||
file->mWasmModule = aModules->ElementAt(moduleIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(blobOrMutableFile.type() ==
|
||||
BlobOrMutableFile::TPBlobChild);
|
||||
|
||||
|
@ -710,6 +727,20 @@ DeserializeStructuredCloneFiles(
|
|||
}
|
||||
|
||||
case StructuredCloneFile::eWasmCompiled: {
|
||||
if (aModules) {
|
||||
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
|
||||
|
||||
StructuredCloneFile* file = aFiles.AppendElement();
|
||||
MOZ_ASSERT(file);
|
||||
|
||||
file->mType = serializedFile.type();
|
||||
|
||||
MOZ_ASSERT(moduleIndex < aModules->Length());
|
||||
file->mWasmModule = aModules->ElementAt(moduleIndex++);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t ||
|
||||
blobOrMutableFile.type() ==
|
||||
BlobOrMutableFile::TPBlobChild);
|
||||
|
@ -910,6 +941,27 @@ DispatchSuccessEvent(ResultHelper* aResultHelper,
|
|||
}
|
||||
}
|
||||
|
||||
PRFileDesc*
|
||||
GetFileDescriptorFromStream(nsIInputStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(aStream);
|
||||
|
||||
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
|
||||
if (NS_WARN_IF(!fileMetadata)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PRFileDesc* fileDesc;
|
||||
nsresult rv = fileMetadata->GetFileDescriptor(&fileDesc);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(fileDesc);
|
||||
|
||||
return fileDesc;
|
||||
}
|
||||
|
||||
class WorkerPermissionChallenge;
|
||||
|
||||
// This class calles WorkerPermissionChallenge::OperationCompleted() in the
|
||||
|
@ -1143,6 +1195,79 @@ WorkerPermissionRequestChildProcessActor::Recv__delete__(
|
|||
|
||||
} // namespace
|
||||
|
||||
/*******************************************************************************
|
||||
* Actor class declarations
|
||||
******************************************************************************/
|
||||
|
||||
// CancelableRunnable is used to make workers happy.
|
||||
class BackgroundRequestChild::PreprocessHelper final
|
||||
: public CancelableRunnable
|
||||
{
|
||||
typedef std::pair<nsCOMPtr<nsIInputStream>,
|
||||
nsCOMPtr<nsIInputStream>> StreamPair;
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
nsTArray<StreamPair> mStreamPairs;
|
||||
nsTArray<RefPtr<JS::WasmModule>> mModules;
|
||||
BackgroundRequestChild* mActor;
|
||||
nsresult mResultCode;
|
||||
|
||||
public:
|
||||
PreprocessHelper(BackgroundRequestChild* aActor)
|
||||
: mOwningThread(NS_GetCurrentThread())
|
||||
, mActor(aActor)
|
||||
, mResultCode(NS_OK)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
aActor->AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
bool
|
||||
IsOnOwningThread() const
|
||||
{
|
||||
MOZ_ASSERT(mOwningThread);
|
||||
|
||||
bool current;
|
||||
return NS_SUCCEEDED(mOwningThread->IsOnCurrentThread(¤t)) && current;
|
||||
}
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwningThread());
|
||||
}
|
||||
|
||||
void
|
||||
ClearActor()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
mActor = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(const nsTArray<StructuredCloneFile>& aFiles);
|
||||
|
||||
nsresult
|
||||
Dispatch();
|
||||
|
||||
private:
|
||||
~PreprocessHelper()
|
||||
{ }
|
||||
|
||||
void
|
||||
RunOnOwningThread();
|
||||
|
||||
nsresult
|
||||
RunOnStreamTransportThread();
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
virtual nsresult
|
||||
Cancel() override;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Local class implementations
|
||||
******************************************************************************/
|
||||
|
@ -2411,6 +2536,36 @@ BackgroundRequestChild::~BackgroundRequestChild()
|
|||
MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::OnPreprocessFinished(
|
||||
const nsTArray<RefPtr<JS::WasmModule>>& aModules)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!aModules.IsEmpty());
|
||||
MOZ_ASSERT(mPreprocessHelper);
|
||||
MOZ_ASSERT(!mModules);
|
||||
|
||||
mModules = new nsTArray<RefPtr<JS::WasmModule>>;
|
||||
*mModules = Move(aModules);
|
||||
|
||||
MOZ_ALWAYS_TRUE(SendContinue(ObjectStoreGetPreprocessResponse()));
|
||||
|
||||
mPreprocessHelper = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::OnPreprocessFailed(nsresult aErrorCode)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(NS_FAILED(aErrorCode));
|
||||
MOZ_ASSERT(mPreprocessHelper);
|
||||
MOZ_ASSERT(!mModules);
|
||||
|
||||
MOZ_ALWAYS_TRUE(SendContinue(aErrorCode));
|
||||
|
||||
mPreprocessHelper = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(nsresult aResponse)
|
||||
{
|
||||
|
@ -2455,7 +2610,8 @@ BackgroundRequestChild::HandleResponse(
|
|||
StructuredCloneReadInfo cloneReadInfo(Move(serializedCloneInfo));
|
||||
|
||||
DeserializeStructuredCloneFiles(mTransaction->Database(),
|
||||
aResponse,
|
||||
aResponse.files(),
|
||||
mModules,
|
||||
cloneReadInfo.mFiles);
|
||||
|
||||
ResultHelper helper(mRequest, mTransaction, &cloneReadInfo);
|
||||
|
@ -2487,7 +2643,10 @@ BackgroundRequestChild::HandleResponse(
|
|||
|
||||
// Get the files
|
||||
nsTArray<StructuredCloneFile> files;
|
||||
DeserializeStructuredCloneFiles(database, serializedCloneInfo, files);
|
||||
DeserializeStructuredCloneFiles(database,
|
||||
serializedCloneInfo.files(),
|
||||
nullptr,
|
||||
files);
|
||||
|
||||
// Move relevant data into the cloneReadInfo
|
||||
*cloneReadInfo = Move(serializedCloneInfo);
|
||||
|
@ -2529,6 +2688,12 @@ BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
|||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
if (mPreprocessHelper) {
|
||||
mPreprocessHelper->ClearActor();
|
||||
|
||||
mPreprocessHelper = nullptr;
|
||||
}
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
|
@ -2629,6 +2794,218 @@ BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundRequestChild::RecvPreprocess(const PreprocessParams& aParams)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mTransaction);
|
||||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
IDBDatabase* database = mTransaction->Database();
|
||||
|
||||
if (aParams.type() != PreprocessParams::TObjectStoreGetPreprocessParams) {
|
||||
MOZ_ASSERT(false, "Fix me!");
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectStoreGetPreprocessParams params =
|
||||
aParams.get_ObjectStoreGetPreprocessParams();
|
||||
|
||||
nsTArray<StructuredCloneFile> files;
|
||||
DeserializeStructuredCloneFiles(database,
|
||||
params.preprocessInfo().files(),
|
||||
nullptr,
|
||||
files);
|
||||
|
||||
mPreprocessHelper = new PreprocessHelper(this);
|
||||
|
||||
nsresult rv = mPreprocessHelper->Init(files);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return SendContinue(rv);
|
||||
}
|
||||
|
||||
rv = mPreprocessHelper->Dispatch();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return SendContinue(rv);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::Init(const nsTArray<StructuredCloneFile>& aFiles)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!aFiles.IsEmpty());
|
||||
|
||||
uint32_t count = aFiles.Length();
|
||||
|
||||
// We should receive even number of files.
|
||||
MOZ_ASSERT(count % 2 == 0);
|
||||
|
||||
// Let's process it as pairs.
|
||||
count = count / 2;
|
||||
|
||||
nsTArray<StreamPair> streamPairs;
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
uint32_t bytecodeIndex = index * 2;
|
||||
uint32_t compiledIndex = bytecodeIndex + 1;
|
||||
|
||||
const StructuredCloneFile& bytecodeFile = aFiles[bytecodeIndex];
|
||||
const StructuredCloneFile& compiledFile = aFiles[compiledIndex];
|
||||
|
||||
MOZ_ASSERT(bytecodeFile.mType == StructuredCloneFile::eWasmBytecode);
|
||||
MOZ_ASSERT(bytecodeFile.mBlob);
|
||||
MOZ_ASSERT(compiledFile.mType == StructuredCloneFile::eWasmCompiled);
|
||||
|
||||
ErrorResult errorResult;
|
||||
|
||||
nsCOMPtr<nsIInputStream> bytecodeStream;
|
||||
bytecodeFile.mBlob->GetInternalStream(getter_AddRefs(bytecodeStream),
|
||||
errorResult);
|
||||
if (NS_WARN_IF(errorResult.Failed())) {
|
||||
return errorResult.StealNSResult();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> compiledStream;
|
||||
if (compiledFile.mBlob) {
|
||||
compiledFile.mBlob->GetInternalStream(getter_AddRefs(compiledStream),
|
||||
errorResult);
|
||||
if (NS_WARN_IF(errorResult.Failed())) {
|
||||
return errorResult.StealNSResult();
|
||||
}
|
||||
}
|
||||
|
||||
streamPairs.AppendElement(StreamPair(bytecodeStream, compiledStream));
|
||||
}
|
||||
|
||||
mStreamPairs = Move(streamPairs);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::Dispatch()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
// The stream transport service is used for asynchronous processing. It has
|
||||
// a threadpool with a high cap of 25 threads. Fortunately, the service can
|
||||
// be used on workers too.
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::RunOnOwningThread()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mActor) {
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
mActor->OnPreprocessFinished(mModules);
|
||||
} else {
|
||||
mActor->OnPreprocessFailed(mResultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::RunOnStreamTransportThread()
|
||||
{
|
||||
MOZ_ASSERT(!IsOnOwningThread());
|
||||
MOZ_ASSERT(!mStreamPairs.IsEmpty());
|
||||
MOZ_ASSERT(mModules.IsEmpty());
|
||||
|
||||
const uint32_t count = mStreamPairs.Length();
|
||||
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
const StreamPair& streamPair = mStreamPairs[index];
|
||||
|
||||
const nsCOMPtr<nsIInputStream>& bytecodeStream = streamPair.first;
|
||||
|
||||
MOZ_ASSERT(bytecodeStream);
|
||||
|
||||
PRFileDesc* bytecodeFileDesc = GetFileDescriptorFromStream(bytecodeStream);
|
||||
if (NS_WARN_IF(!bytecodeFileDesc)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
const nsCOMPtr<nsIInputStream>& compiledStream = streamPair.second;
|
||||
|
||||
PRFileDesc* compiledFileDesc;
|
||||
if (compiledStream) {
|
||||
compiledFileDesc = GetFileDescriptorFromStream(compiledStream);
|
||||
if (NS_WARN_IF(!bytecodeFileDesc)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
compiledFileDesc = nullptr;
|
||||
}
|
||||
|
||||
JS::BuildIdCharVector buildId;
|
||||
bool ok = GetBuildId(&buildId);
|
||||
if (NS_WARN_IF(!ok)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<JS::WasmModule> module = JS::DeserializeWasmModule(bytecodeFileDesc,
|
||||
compiledFileDesc,
|
||||
Move(buildId),
|
||||
nullptr,
|
||||
0,
|
||||
0);
|
||||
if (NS_WARN_IF(!module)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mModules.AppendElement(module);
|
||||
}
|
||||
|
||||
mStreamPairs.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::Run()
|
||||
{
|
||||
if (IsOnOwningThread()) {
|
||||
RunOnOwningThread();
|
||||
} else {
|
||||
nsresult rv = RunOnStreamTransportThread();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
MOZ_ASSERT(mResultCode == NS_OK);
|
||||
mResultCode = rv;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundRequestChild::
|
||||
PreprocessHelper::Cancel()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* BackgroundCursorChild
|
||||
******************************************************************************/
|
||||
|
@ -2826,7 +3203,8 @@ BackgroundCursorChild::HandleResponse(
|
|||
cloneReadInfo.mDatabase = mTransaction->Database();
|
||||
|
||||
DeserializeStructuredCloneFiles(mTransaction->Database(),
|
||||
response.cloneInfo(),
|
||||
response.cloneInfo().files(),
|
||||
nullptr,
|
||||
cloneReadInfo.mFiles);
|
||||
|
||||
RefPtr<IDBCursor> newCursor;
|
||||
|
@ -2889,7 +3267,8 @@ BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
|
|||
cloneReadInfo.mDatabase = mTransaction->Database();
|
||||
|
||||
DeserializeStructuredCloneFiles(mTransaction->Database(),
|
||||
aResponse.cloneInfo(),
|
||||
aResponse.cloneInfo().files(),
|
||||
nullptr,
|
||||
cloneReadInfo.mFiles);
|
||||
|
||||
RefPtr<IDBCursor> newCursor;
|
||||
|
|
|
@ -29,6 +29,10 @@ class nsIEventTarget;
|
|||
struct nsID;
|
||||
struct PRThread;
|
||||
|
||||
namespace JS {
|
||||
struct WasmModule;
|
||||
} // namespace JS
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
|
@ -640,7 +644,11 @@ class BackgroundRequestChild final
|
|||
friend class BackgroundVersionChangeTransactionChild;
|
||||
friend IDBTransaction;
|
||||
|
||||
class PreprocessHelper;
|
||||
|
||||
RefPtr<IDBTransaction> mTransaction;
|
||||
RefPtr<PreprocessHelper> mPreprocessHelper;
|
||||
nsAutoPtr<nsTArray<RefPtr<JS::WasmModule>>> mModules;
|
||||
|
||||
private:
|
||||
// Only created by IDBTransaction.
|
||||
|
@ -651,6 +659,12 @@ private:
|
|||
// BackgroundVersionChangeTransactionChild.
|
||||
~BackgroundRequestChild();
|
||||
|
||||
void
|
||||
OnPreprocessFinished(const nsTArray<RefPtr<JS::WasmModule>>& aModules);
|
||||
|
||||
void
|
||||
OnPreprocessFailed(nsresult aErrorCode);
|
||||
|
||||
void
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
|
@ -678,6 +692,9 @@ private:
|
|||
|
||||
virtual bool
|
||||
Recv__delete__(const RequestResponse& aResponse) override;
|
||||
|
||||
virtual bool
|
||||
RecvPreprocess(const PreprocessParams& aParams) override;
|
||||
};
|
||||
|
||||
class BackgroundCursorChild final
|
||||
|
|
|
@ -5926,13 +5926,15 @@ protected:
|
|||
uint32_t aDataIndex,
|
||||
uint32_t aFileIdsIndex,
|
||||
FileManager* aFileManager,
|
||||
StructuredCloneReadInfo* aInfo)
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm)
|
||||
{
|
||||
return GetStructuredCloneReadInfoFromSource(aStatement,
|
||||
aDataIndex,
|
||||
aFileIdsIndex,
|
||||
aFileManager,
|
||||
aInfo);
|
||||
aInfo,
|
||||
aHasWasm);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
|
@ -5942,11 +5944,13 @@ protected:
|
|||
FileManager* aFileManager,
|
||||
StructuredCloneReadInfo* aInfo)
|
||||
{
|
||||
bool dummy;
|
||||
return GetStructuredCloneReadInfoFromSource(aValues,
|
||||
aDataIndex,
|
||||
aFileIdsIndex,
|
||||
aFileManager,
|
||||
aInfo);
|
||||
aInfo,
|
||||
&dummy);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
|
@ -6010,20 +6014,23 @@ private:
|
|||
uint32_t aDataIndex,
|
||||
uint32_t aFileIdsIndex,
|
||||
FileManager* aFileManager,
|
||||
StructuredCloneReadInfo* aInfo);
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm);
|
||||
|
||||
static nsresult
|
||||
GetStructuredCloneReadInfoFromBlob(const uint8_t* aBlobData,
|
||||
uint32_t aBlobDataLength,
|
||||
FileManager* aFileManager,
|
||||
const nsAString& aFileIds,
|
||||
StructuredCloneReadInfo* aInfo);
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm);
|
||||
|
||||
static nsresult
|
||||
GetStructuredCloneReadInfoFromExternalBlob(uint64_t aIntData,
|
||||
FileManager* aFileManager,
|
||||
const nsAString& aFileIds,
|
||||
StructuredCloneReadInfo* aInfo);
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm);
|
||||
|
||||
// Not to be overridden by subclasses.
|
||||
NS_DECL_MOZISTORAGEPROGRESSHANDLER
|
||||
|
@ -6049,8 +6056,19 @@ public:
|
|||
class TransactionDatabaseOperationBase
|
||||
: public DatabaseOperationBase
|
||||
{
|
||||
enum class InternalState
|
||||
{
|
||||
Initial,
|
||||
DatabaseWork,
|
||||
SendingPreprocess,
|
||||
WaitingForContinue,
|
||||
SendingResults,
|
||||
Completed
|
||||
};
|
||||
|
||||
RefPtr<TransactionBase> mTransaction;
|
||||
const int64_t mTransactionLoggingSerialNumber;
|
||||
InternalState mInternalState;
|
||||
const bool mTransactionIsAborted;
|
||||
|
||||
public:
|
||||
|
@ -6062,6 +6080,13 @@ public:
|
|||
{ }
|
||||
#endif
|
||||
|
||||
uint64_t
|
||||
StartOnConnectionPool(const nsID& aBackgroundChildLoggingId,
|
||||
const nsACString& aDatabaseId,
|
||||
int64_t aLoggingSerialNumber,
|
||||
const nsTArray<nsString>& aObjectStoreNames,
|
||||
bool aIsWriteTransaction);
|
||||
|
||||
void
|
||||
DispatchToConnectionPool();
|
||||
|
||||
|
@ -6073,6 +6098,9 @@ public:
|
|||
return mTransaction;
|
||||
}
|
||||
|
||||
void
|
||||
NoteContinueReceived();
|
||||
|
||||
// May be overridden by subclasses if they need to perform work on the
|
||||
// background thread before being dispatched. Returning false will kill the
|
||||
// child actors and prevent dispatch.
|
||||
|
@ -6105,6 +6133,19 @@ protected:
|
|||
virtual nsresult
|
||||
DoDatabaseWork(DatabaseConnection* aConnection) = 0;
|
||||
|
||||
// May be overriden in subclasses. Called on the background thread to decide
|
||||
// if the subclass needs to send any preprocess info to the child actor.
|
||||
virtual bool
|
||||
HasPreprocessInfo();
|
||||
|
||||
// May be overriden in subclasses. Called on the background thread to allow
|
||||
// the subclass to serialize its preprocess info and send it to the child
|
||||
// actor. A successful return value will trigger a wait for a
|
||||
// NoteContinueReceived callback on the background thread while a failure
|
||||
// value will trigger a SendFailureResult callback.
|
||||
virtual nsresult
|
||||
SendPreprocessInfo();
|
||||
|
||||
// Must be overridden in subclasses. Called on the background thread to allow
|
||||
// the subclass to serialize its results and send them to the child actor. A
|
||||
// failed return value will trigger a SendFailureResult callback.
|
||||
|
@ -6120,7 +6161,16 @@ protected:
|
|||
|
||||
private:
|
||||
void
|
||||
RunOnOwningThread();
|
||||
SendToConnectionPool();
|
||||
|
||||
void
|
||||
SendPreprocess();
|
||||
|
||||
void
|
||||
SendResults();
|
||||
|
||||
void
|
||||
SendPreprocessInfoOrResults(bool aSendPreprocessInfo);
|
||||
|
||||
// Not to be overridden by subclasses.
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
@ -6198,7 +6248,6 @@ private:
|
|||
class WaitForTransactionsHelper final
|
||||
: public Runnable
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
const nsCString mDatabaseId;
|
||||
nsCOMPtr<nsIRunnable> mCallback;
|
||||
|
||||
|
@ -6213,8 +6262,7 @@ class WaitForTransactionsHelper final
|
|||
public:
|
||||
WaitForTransactionsHelper(const nsCString& aDatabaseId,
|
||||
nsIRunnable* aCallback)
|
||||
: mOwningThread(NS_GetCurrentThread())
|
||||
, mDatabaseId(aDatabaseId)
|
||||
: mDatabaseId(aDatabaseId)
|
||||
, mCallback(aCallback)
|
||||
, mState(State::Initial)
|
||||
{
|
||||
|
@ -8137,6 +8185,9 @@ private:
|
|||
// IPDL methods.
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
virtual bool
|
||||
RecvContinue(const PreprocessResponse& aResponse) override;
|
||||
};
|
||||
|
||||
class ObjectStoreAddOrPutRequestOp final
|
||||
|
@ -8291,6 +8342,7 @@ class ObjectStoreGetRequestOp final
|
|||
PBackgroundParent* mBackgroundParent;
|
||||
const uint32_t mLimit;
|
||||
const bool mGetAll;
|
||||
bool mHasWasm;
|
||||
|
||||
private:
|
||||
// Only created by TransactionBase.
|
||||
|
@ -8308,6 +8360,12 @@ private:
|
|||
virtual nsresult
|
||||
DoDatabaseWork(DatabaseConnection* aConnection) override;
|
||||
|
||||
virtual bool
|
||||
HasPreprocessInfo() override;
|
||||
|
||||
virtual nsresult
|
||||
SendPreprocessInfo() override;
|
||||
|
||||
virtual void
|
||||
GetResponse(RequestResponse& aResponse) override;
|
||||
};
|
||||
|
@ -9647,9 +9705,11 @@ DeserializeStructuredCloneFile(FileManager* aFileManager,
|
|||
nsresult
|
||||
DeserializeStructuredCloneFiles(FileManager* aFileManager,
|
||||
const nsAString& aText,
|
||||
nsTArray<StructuredCloneFile>& aResult)
|
||||
nsTArray<StructuredCloneFile>& aResult,
|
||||
bool* aHasWasm)
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(aHasWasm);
|
||||
|
||||
nsCharSeparatedTokenizerTemplate<TokenizerIgnoreNothing>
|
||||
tokenizer(aText, ' ');
|
||||
|
@ -9668,7 +9728,12 @@ DeserializeStructuredCloneFiles(FileManager* aFileManager,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (file->mType == StructuredCloneFile::eWasmCompiled) {
|
||||
if (file->mType == StructuredCloneFile::eWasmBytecode) {
|
||||
MOZ_ASSERT(file->mValid);
|
||||
|
||||
*aHasWasm = true;
|
||||
}
|
||||
else if (file->mType == StructuredCloneFile::eWasmCompiled) {
|
||||
if (!directory) {
|
||||
directory = aFileManager->GetCheckedDirectory();
|
||||
if (NS_WARN_IF(!directory)) {
|
||||
|
@ -9700,6 +9765,8 @@ DeserializeStructuredCloneFiles(FileManager* aFileManager,
|
|||
MOZ_ASSERT(file->mValid);
|
||||
file->mValid = JS::CompiledWasmModuleAssumptionsMatch(fileDesc,
|
||||
Move(buildId));
|
||||
|
||||
*aHasWasm = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9733,6 +9800,7 @@ SerializeStructuredCloneFiles(
|
|||
PBackgroundParent* aBackgroundActor,
|
||||
Database* aDatabase,
|
||||
const nsTArray<StructuredCloneFile>& aFiles,
|
||||
bool aForPreprocess,
|
||||
FallibleTArray<SerializedStructuredCloneFile>& aResult)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
@ -9761,6 +9829,12 @@ SerializeStructuredCloneFiles(
|
|||
for (uint32_t index = 0; index < count; index++) {
|
||||
const StructuredCloneFile& file = aFiles[index];
|
||||
|
||||
if (aForPreprocess &&
|
||||
file.mType != StructuredCloneFile::eWasmBytecode &&
|
||||
file.mType != StructuredCloneFile::eWasmCompiled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int64_t fileId = file.mFileInfo->Id();
|
||||
MOZ_ASSERT(fileId > 0);
|
||||
|
||||
|
@ -9842,13 +9916,13 @@ SerializeStructuredCloneFiles(
|
|||
|
||||
case StructuredCloneFile::eWasmBytecode:
|
||||
case StructuredCloneFile::eWasmCompiled: {
|
||||
if (file.mType == StructuredCloneFile::eWasmCompiled && !file.mValid) {
|
||||
if (!aForPreprocess || !file.mValid) {
|
||||
SerializedStructuredCloneFile* serializedFile =
|
||||
aResult.AppendElement(fallible);
|
||||
MOZ_ASSERT(serializedFile);
|
||||
|
||||
serializedFile->file() = null_t();
|
||||
serializedFile->type() = StructuredCloneFile::eWasmCompiled;
|
||||
serializedFile->type() = file.mType;
|
||||
} else {
|
||||
RefPtr<BlobImpl> impl = new BlobImplStoredFile(nativeFile,
|
||||
file.mFileInfo,
|
||||
|
@ -11457,7 +11531,8 @@ UpdateRefcountFunction::ProcessValue(mozIStorageValueArray* aValues,
|
|||
}
|
||||
|
||||
nsTArray<StructuredCloneFile> files;
|
||||
rv = DeserializeStructuredCloneFiles(mFileManager, ids, files);
|
||||
bool dummy;
|
||||
rv = DeserializeStructuredCloneFiles(mFileManager, ids, files, &dummy);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -14390,12 +14465,11 @@ Database::RecvPBackgroundIDBTransactionConstructor(
|
|||
RefPtr<StartTransactionOp> startOp = new StartTransactionOp(transaction);
|
||||
|
||||
uint64_t transactionId =
|
||||
gConnectionPool->Start(GetLoggingInfo()->Id(),
|
||||
mMetadata->mDatabaseId,
|
||||
transaction->LoggingSerialNumber(),
|
||||
aObjectStoreNames,
|
||||
aMode != IDBTransaction::READ_ONLY,
|
||||
startOp);
|
||||
startOp->StartOnConnectionPool(GetLoggingInfo()->Id(),
|
||||
mMetadata->mDatabaseId,
|
||||
transaction->LoggingSerialNumber(),
|
||||
aObjectStoreNames,
|
||||
aMode != IDBTransaction::READ_ONLY);
|
||||
|
||||
transaction->SetActive(transactionId);
|
||||
|
||||
|
@ -16593,6 +16667,7 @@ Cursor::SendResponseInternal(
|
|||
nsresult rv = SerializeStructuredCloneFiles(mBackgroundParent,
|
||||
mDatabase,
|
||||
files,
|
||||
/* aForPreprocess */ false,
|
||||
serializedFiles);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aResponse = ClampResultCode(rv);
|
||||
|
@ -19269,7 +19344,8 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromSource(
|
|||
uint32_t aDataIndex,
|
||||
uint32_t aFileIdsIndex,
|
||||
FileManager* aFileManager,
|
||||
StructuredCloneReadInfo* aInfo)
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm)
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(aSource);
|
||||
|
@ -19312,7 +19388,8 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromSource(
|
|||
rv = GetStructuredCloneReadInfoFromExternalBlob(intData,
|
||||
aFileManager,
|
||||
fileIds,
|
||||
aInfo);
|
||||
aInfo,
|
||||
aHasWasm);
|
||||
} else {
|
||||
const uint8_t* blobData;
|
||||
uint32_t blobDataLength;
|
||||
|
@ -19326,7 +19403,8 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromSource(
|
|||
blobDataLength,
|
||||
aFileManager,
|
||||
fileIds,
|
||||
aInfo);
|
||||
aInfo,
|
||||
aHasWasm);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -19342,7 +19420,8 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromBlob(
|
|||
uint32_t aBlobDataLength,
|
||||
FileManager* aFileManager,
|
||||
const nsAString& aFileIds,
|
||||
StructuredCloneReadInfo* aInfo)
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm)
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(aFileManager);
|
||||
|
@ -19378,8 +19457,10 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromBlob(
|
|||
}
|
||||
|
||||
if (!aFileIds.IsVoid()) {
|
||||
nsresult rv =
|
||||
DeserializeStructuredCloneFiles(aFileManager, aFileIds, aInfo->mFiles);
|
||||
nsresult rv = DeserializeStructuredCloneFiles(aFileManager,
|
||||
aFileIds,
|
||||
aInfo->mFiles,
|
||||
aHasWasm);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -19394,7 +19475,8 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromExternalBlob(
|
|||
uint64_t aIntData,
|
||||
FileManager* aFileManager,
|
||||
const nsAString& aFileIds,
|
||||
StructuredCloneReadInfo* aInfo)
|
||||
StructuredCloneReadInfo* aInfo,
|
||||
bool* aHasWasm)
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(aFileManager);
|
||||
|
@ -19408,7 +19490,10 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromExternalBlob(
|
|||
nsresult rv;
|
||||
|
||||
if (!aFileIds.IsVoid()) {
|
||||
rv = DeserializeStructuredCloneFiles(aFileManager, aFileIds, aInfo->mFiles);
|
||||
rv = DeserializeStructuredCloneFiles(aFileManager,
|
||||
aFileIds,
|
||||
aInfo->mFiles,
|
||||
aHasWasm);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -21955,12 +22040,12 @@ OpenDatabaseOp::DispatchToWorkThread()
|
|||
RefPtr<VersionChangeOp> versionChangeOp = new VersionChangeOp(this);
|
||||
|
||||
uint64_t transactionId =
|
||||
gConnectionPool->Start(backgroundChildLoggingId,
|
||||
mVersionChangeTransaction->DatabaseId(),
|
||||
loggingSerialNumber,
|
||||
objectStoreNames,
|
||||
/* aIsWriteTransaction */ true,
|
||||
versionChangeOp);
|
||||
versionChangeOp->StartOnConnectionPool(
|
||||
backgroundChildLoggingId,
|
||||
mVersionChangeTransaction->DatabaseId(),
|
||||
loggingSerialNumber,
|
||||
objectStoreNames,
|
||||
/* aIsWriteTransaction */ true);
|
||||
|
||||
mVersionChangeOp = versionChangeOp;
|
||||
|
||||
|
@ -23087,6 +23172,7 @@ TransactionDatabaseOperationBase::TransactionDatabaseOperationBase(
|
|||
aTransaction->GetLoggingInfo()->NextRequestSN())
|
||||
, mTransaction(aTransaction)
|
||||
, mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber())
|
||||
, mInternalState(InternalState::Initial)
|
||||
, mTransactionIsAborted(aTransaction->IsAborted())
|
||||
{
|
||||
MOZ_ASSERT(aTransaction);
|
||||
|
@ -23100,6 +23186,7 @@ TransactionDatabaseOperationBase::TransactionDatabaseOperationBase(
|
|||
aLoggingSerialNumber)
|
||||
, mTransaction(aTransaction)
|
||||
, mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber())
|
||||
, mInternalState(InternalState::Initial)
|
||||
, mTransactionIsAborted(aTransaction->IsAborted())
|
||||
{
|
||||
MOZ_ASSERT(aTransaction);
|
||||
|
@ -23107,6 +23194,7 @@ TransactionDatabaseOperationBase::TransactionDatabaseOperationBase(
|
|||
|
||||
TransactionDatabaseOperationBase::~TransactionDatabaseOperationBase()
|
||||
{
|
||||
MOZ_ASSERT(mInternalState == InternalState::Completed);
|
||||
MOZ_ASSERT(!mTransaction,
|
||||
"TransactionDatabaseOperationBase::Cleanup() was not called by a "
|
||||
"subclass!");
|
||||
|
@ -23123,20 +23211,43 @@ TransactionDatabaseOperationBase::AssertIsOnConnectionThread() const
|
|||
|
||||
#endif // DEBUG
|
||||
|
||||
uint64_t
|
||||
TransactionDatabaseOperationBase::StartOnConnectionPool(
|
||||
const nsID& aBackgroundChildLoggingId,
|
||||
const nsACString& aDatabaseId,
|
||||
int64_t aLoggingSerialNumber,
|
||||
const nsTArray<nsString>& aObjectStoreNames,
|
||||
bool aIsWriteTransaction)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::Initial);
|
||||
|
||||
// Must set mInternalState before dispatching otherwise we will race with the
|
||||
// connection thread.
|
||||
mInternalState = InternalState::DatabaseWork;
|
||||
|
||||
return gConnectionPool->Start(aBackgroundChildLoggingId,
|
||||
aDatabaseId,
|
||||
aLoggingSerialNumber,
|
||||
aObjectStoreNames,
|
||||
aIsWriteTransaction,
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::DispatchToConnectionPool()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::Initial);
|
||||
|
||||
gConnectionPool->Dispatch(mTransaction->TransactionId(), this);
|
||||
|
||||
mTransaction->NoteActiveRequest();
|
||||
Unused << this->Run();
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::RunOnConnectionThread()
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(mInternalState == InternalState::DatabaseWork);
|
||||
MOZ_ASSERT(mTransaction);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(mResultCode));
|
||||
|
||||
|
@ -23203,15 +23314,87 @@ TransactionDatabaseOperationBase::RunOnConnectionThread()
|
|||
}
|
||||
}
|
||||
|
||||
// Must set mInternalState before dispatching otherwise we will race with the
|
||||
// owning thread.
|
||||
if (HasPreprocessInfo()) {
|
||||
mInternalState = InternalState::SendingPreprocess;
|
||||
} else {
|
||||
mInternalState = InternalState::SendingResults;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
bool
|
||||
TransactionDatabaseOperationBase::HasPreprocessInfo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TransactionDatabaseOperationBase::SendPreprocessInfo()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::RunOnOwningThread()
|
||||
TransactionDatabaseOperationBase::NoteContinueReceived()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::WaitingForContinue);
|
||||
|
||||
mInternalState = InternalState::SendingResults;
|
||||
|
||||
Unused << this->Run();
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::SendToConnectionPool()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::Initial);
|
||||
|
||||
// Must set mInternalState before dispatching otherwise we will race with the
|
||||
// connection thread.
|
||||
mInternalState = InternalState::DatabaseWork;
|
||||
|
||||
gConnectionPool->Dispatch(mTransaction->TransactionId(), this);
|
||||
|
||||
mTransaction->NoteActiveRequest();
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::SendPreprocess()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::SendingPreprocess);
|
||||
|
||||
SendPreprocessInfoOrResults(/* aSendPreprocessInfo */ true);
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::SendResults()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::SendingResults);
|
||||
|
||||
SendPreprocessInfoOrResults(/* aSendPreprocessInfo */ false);
|
||||
}
|
||||
|
||||
void
|
||||
TransactionDatabaseOperationBase::SendPreprocessInfoOrResults(
|
||||
bool aSendPreprocessInfo)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::SendingPreprocess ||
|
||||
mInternalState == InternalState::SendingResults);
|
||||
MOZ_ASSERT(mTransaction);
|
||||
|
||||
// Only needed if we're being called from within NoteContinueReceived() since
|
||||
// this TransactionDatabaseOperationBase is only held alive by the IPDL.
|
||||
// SendSuccessResult/SendFailureResult releases that last reference.
|
||||
RefPtr<TransactionDatabaseOperationBase> kungFuDeathGrip;
|
||||
|
||||
if (NS_WARN_IF(IsActorDestroyed())) {
|
||||
// Don't send any notifications if the actor was destroyed already.
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
|
@ -23219,13 +23402,22 @@ TransactionDatabaseOperationBase::RunOnOwningThread()
|
|||
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
} else {
|
||||
if (!aSendPreprocessInfo) {
|
||||
kungFuDeathGrip = this;
|
||||
}
|
||||
|
||||
if (mTransaction->IsInvalidated() || mTransaction->IsAborted()) {
|
||||
// Aborted transactions always see their requests fail with ABORT_ERR,
|
||||
// even if the request succeeded or failed with another error.
|
||||
mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
|
||||
} else if (NS_SUCCEEDED(mResultCode)) {
|
||||
// This may release the IPDL reference.
|
||||
mResultCode = SendSuccessResult();
|
||||
if (aSendPreprocessInfo) {
|
||||
// This should not release the IPDL reference.
|
||||
mResultCode = SendPreprocessInfo();
|
||||
} else {
|
||||
// This may release the IPDL reference.
|
||||
mResultCode = SendSuccessResult();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(mResultCode)) {
|
||||
|
@ -23237,17 +23429,24 @@ TransactionDatabaseOperationBase::RunOnOwningThread()
|
|||
}
|
||||
}
|
||||
|
||||
if (mLoggingSerialNumber) {
|
||||
mTransaction->NoteFinishedRequest();
|
||||
}
|
||||
if (aSendPreprocessInfo && NS_SUCCEEDED(mResultCode)) {
|
||||
mInternalState = InternalState::WaitingForContinue;
|
||||
} else {
|
||||
if (mLoggingSerialNumber) {
|
||||
mTransaction->NoteFinishedRequest();
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
Cleanup();
|
||||
|
||||
mInternalState = InternalState::Completed;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TransactionDatabaseOperationBase::Init(TransactionBase* aTransaction)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::Initial);
|
||||
MOZ_ASSERT(aTransaction);
|
||||
|
||||
return true;
|
||||
|
@ -23257,6 +23456,7 @@ void
|
|||
TransactionDatabaseOperationBase::Cleanup()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mInternalState == InternalState::SendingResults);
|
||||
MOZ_ASSERT(mTransaction);
|
||||
|
||||
mTransaction = nullptr;
|
||||
|
@ -23265,15 +23465,26 @@ TransactionDatabaseOperationBase::Cleanup()
|
|||
NS_IMETHODIMP
|
||||
TransactionDatabaseOperationBase::Run()
|
||||
{
|
||||
MOZ_ASSERT(mTransaction);
|
||||
switch (mInternalState) {
|
||||
case InternalState::Initial:
|
||||
SendToConnectionPool();
|
||||
return NS_OK;
|
||||
|
||||
if (IsOnBackgroundThread()) {
|
||||
RunOnOwningThread();
|
||||
} else {
|
||||
RunOnConnectionThread();
|
||||
case InternalState::DatabaseWork:
|
||||
RunOnConnectionThread();
|
||||
return NS_OK;
|
||||
|
||||
case InternalState::SendingPreprocess:
|
||||
SendPreprocess();
|
||||
return NS_OK;
|
||||
|
||||
case InternalState::SendingResults:
|
||||
SendResults();
|
||||
return NS_OK;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad state!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TransactionBase::
|
||||
|
@ -25470,6 +25681,28 @@ NormalTransactionOp::ActorDestroy(ActorDestroyReason aWhy)
|
|||
NoteActorDestroyed();
|
||||
}
|
||||
|
||||
bool
|
||||
NormalTransactionOp::RecvContinue(const PreprocessResponse& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
switch (aResponse.type()) {
|
||||
case PreprocessResponse::Tnsresult:
|
||||
mResultCode = aResponse.get_nsresult();
|
||||
break;
|
||||
|
||||
case PreprocessResponse::TObjectStoreGetPreprocessResponse:
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
NoteContinueReceived();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectStoreAddOrPutRequestOp::ObjectStoreAddOrPutRequestOp(
|
||||
TransactionBase* aTransaction,
|
||||
const RequestParams& aParams)
|
||||
|
@ -26333,6 +26566,7 @@ ObjectStoreGetRequestOp::ObjectStoreGetRequestOp(TransactionBase* aTransaction,
|
|||
, mBackgroundParent(aTransaction->GetBackgroundParent())
|
||||
, mLimit(aGetAll ? aParams.get_ObjectStoreGetAllParams().limit() : 1)
|
||||
, mGetAll(aGetAll)
|
||||
, mHasWasm(false)
|
||||
{
|
||||
MOZ_ASSERT(aParams.type() == RequestParams::TObjectStoreGetParams ||
|
||||
aParams.type() == RequestParams::TObjectStoreGetAllParams);
|
||||
|
@ -26359,6 +26593,7 @@ ObjectStoreGetRequestOp::ConvertResponse(
|
|||
nsresult rv = SerializeStructuredCloneFiles(mBackgroundParent,
|
||||
mDatabase,
|
||||
info.mFiles,
|
||||
/* aForPreprocess */ false,
|
||||
serializedFiles);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -26437,7 +26672,8 @@ ObjectStoreGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt, 1, 0,
|
||||
mDatabase->GetFileManager(),
|
||||
cloneInfo);
|
||||
cloneInfo,
|
||||
&mHasWasm);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -26452,6 +26688,53 @@ ObjectStoreGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectStoreGetRequestOp::HasPreprocessInfo()
|
||||
{
|
||||
return mHasWasm;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ObjectStoreGetRequestOp::SendPreprocessInfo()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!IsActorDestroyed());
|
||||
MOZ_ASSERT(!mResponse.IsEmpty());
|
||||
|
||||
if (mGetAll) {
|
||||
MOZ_ASSERT(false, "Fix me!");
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo& cloneInfo = mResponse[0];
|
||||
|
||||
FallibleTArray<SerializedStructuredCloneFile> serializedFiles;
|
||||
nsresult rv = SerializeStructuredCloneFiles(mBackgroundParent,
|
||||
mDatabase,
|
||||
cloneInfo.mFiles,
|
||||
/* aForPreprocess */ true,
|
||||
serializedFiles);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
WasmModulePreprocessInfo preprocessInfo;
|
||||
|
||||
MOZ_ASSERT(preprocessInfo.files().IsEmpty());
|
||||
|
||||
preprocessInfo.files().SwapElements(serializedFiles);
|
||||
|
||||
PreprocessParams params = ObjectStoreGetPreprocessParams(preprocessInfo);
|
||||
|
||||
if (NS_WARN_IF(!PBackgroundIDBRequestParent::SendPreprocess(params))) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ObjectStoreGetRequestOp::GetResponse(RequestResponse& aResponse)
|
||||
{
|
||||
|
@ -27035,9 +27318,11 @@ IndexGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
bool dummy;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt, 1, 0,
|
||||
mDatabase->GetFileManager(),
|
||||
cloneInfo);
|
||||
cloneInfo,
|
||||
&dummy);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -27082,6 +27367,7 @@ IndexGetRequestOp::GetResponse(RequestResponse& aResponse)
|
|||
nsresult rv = SerializeStructuredCloneFiles(mBackgroundParent,
|
||||
mDatabase,
|
||||
info.mFiles,
|
||||
/* aForPreprocess */ false,
|
||||
serializedFiles);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aResponse = rv;
|
||||
|
@ -27117,6 +27403,7 @@ IndexGetRequestOp::GetResponse(RequestResponse& aResponse)
|
|||
SerializeStructuredCloneFiles(mBackgroundParent,
|
||||
mDatabase,
|
||||
info.mFiles,
|
||||
/* aForPreprocess */ false,
|
||||
serializedFiles);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aResponse = rv;
|
||||
|
@ -27406,11 +27693,13 @@ CursorOpBase::PopulateResponseFromStatement(
|
|||
switch (mCursor->mType) {
|
||||
case OpenCursorParams::TObjectStoreOpenCursorParams: {
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
bool dummy;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
|
||||
2,
|
||||
1,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
&cloneInfo,
|
||||
&dummy);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -27449,11 +27738,13 @@ CursorOpBase::PopulateResponseFromStatement(
|
|||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
bool dummy;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
|
||||
4,
|
||||
3,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
&cloneInfo,
|
||||
&dummy);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -190,25 +190,6 @@ GenerateRequest(JSContext* aCx, IDBObjectStore* aObjectStore)
|
|||
return request.forget();
|
||||
}
|
||||
|
||||
PRFileDesc*
|
||||
GetFileDescriptorFromStream(nsIInputStream* aStream)
|
||||
{
|
||||
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
|
||||
if (NS_WARN_IF(!fileMetadata)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PRFileDesc* fileDesc;
|
||||
nsresult rv = fileMetadata->GetFileDescriptor(&fileDesc);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(fileDesc);
|
||||
|
||||
return fileDesc;
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneWriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
|
@ -396,6 +377,9 @@ StructuredCloneWriteCallback(JSContext* aCx,
|
|||
|
||||
const uint32_t index = cloneWriteInfo->mFiles.Length();
|
||||
|
||||
// The ordering of the bytecode and compiled file is significant and must
|
||||
// never be changed. These two files must always form a pair
|
||||
// [eWasmBytecode, eWasmCompiled]. Everything else depends on it!
|
||||
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_WASM, /* flags */ 0) ||
|
||||
!JS_WriteUint32Pair(aWriter, index, index + 1)) {
|
||||
return false;
|
||||
|
@ -745,66 +729,16 @@ public:
|
|||
|
||||
static bool
|
||||
CreateAndWrapWasmModule(JSContext* aCx,
|
||||
StructuredCloneFile& aBytecodeFile,
|
||||
StructuredCloneFile& aCompiledFile,
|
||||
StructuredCloneFile& aFile,
|
||||
const WasmModuleData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aBytecodeFile.mType == StructuredCloneFile::eWasmBytecode);
|
||||
MOZ_ASSERT(aBytecodeFile.mBlob);
|
||||
MOZ_ASSERT(aCompiledFile.mType == StructuredCloneFile::eWasmCompiled);
|
||||
MOZ_ASSERT(aFile.mType == StructuredCloneFile::eWasmCompiled);
|
||||
MOZ_ASSERT(!aFile.mBlob);
|
||||
MOZ_ASSERT(aFile.mWasmModule);
|
||||
|
||||
ErrorResult errorResult;
|
||||
|
||||
nsCOMPtr<nsIInputStream> bytecodeStream;
|
||||
aBytecodeFile.mBlob->GetInternalStream(getter_AddRefs(bytecodeStream),
|
||||
errorResult);
|
||||
if (NS_WARN_IF(errorResult.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PRFileDesc* bytecodeFileDesc = GetFileDescriptorFromStream(bytecodeStream);
|
||||
if (NS_WARN_IF(!bytecodeFileDesc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The compiled stream must scoped here!
|
||||
nsCOMPtr<nsIInputStream> compiledStream;
|
||||
|
||||
PRFileDesc* compiledFileDesc;
|
||||
if (aCompiledFile.mBlob) {
|
||||
aCompiledFile.mBlob->GetInternalStream(getter_AddRefs(compiledStream),
|
||||
errorResult);
|
||||
if (NS_WARN_IF(errorResult.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
compiledFileDesc = GetFileDescriptorFromStream(compiledStream);
|
||||
if (NS_WARN_IF(!compiledFileDesc)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
compiledFileDesc = nullptr;
|
||||
}
|
||||
|
||||
JS::BuildIdCharVector buildId;
|
||||
bool ok = GetBuildId(&buildId);
|
||||
if (NS_WARN_IF(!ok)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<JS::WasmModule> module = JS::DeserializeWasmModule(bytecodeFileDesc,
|
||||
compiledFileDesc,
|
||||
Move(buildId),
|
||||
nullptr,
|
||||
0,
|
||||
0);
|
||||
if (NS_WARN_IF(!module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> moduleObj(aCx, module->createObject(aCx));
|
||||
JS::Rooted<JSObject*> moduleObj(aCx, aFile.mWasmModule->createObject(aCx));
|
||||
if (NS_WARN_IF(!moduleObj)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -907,8 +841,7 @@ public:
|
|||
|
||||
static bool
|
||||
CreateAndWrapWasmModule(JSContext* aCx,
|
||||
StructuredCloneFile& aBytecodeFile,
|
||||
StructuredCloneFile& aCompiledFile,
|
||||
StructuredCloneFile& aFile,
|
||||
const WasmModuleData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
|
@ -980,14 +913,12 @@ public:
|
|||
|
||||
static bool
|
||||
CreateAndWrapWasmModule(JSContext* aCx,
|
||||
StructuredCloneFile& aBytecodeFile,
|
||||
StructuredCloneFile& aCompiledFile,
|
||||
StructuredCloneFile& aFile,
|
||||
const WasmModuleData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aBytecodeFile.mType == StructuredCloneFile::eBlob);
|
||||
MOZ_ASSERT(aCompiledFile.mType == StructuredCloneFile::eBlob);
|
||||
MOZ_ASSERT(aFile.mType == StructuredCloneFile::eBlob);
|
||||
|
||||
MOZ_ASSERT(false, "This should never be possible!");
|
||||
|
||||
|
@ -1039,14 +970,10 @@ CommonStructuredCloneReadCallback(JSContext* aCx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
StructuredCloneFile& bytecodeFile =
|
||||
cloneReadInfo->mFiles[data.bytecodeIndex];
|
||||
StructuredCloneFile& compiledFile =
|
||||
cloneReadInfo->mFiles[data.compiledIndex];
|
||||
StructuredCloneFile& file = cloneReadInfo->mFiles[data.compiledIndex];
|
||||
|
||||
if (NS_WARN_IF(!Traits::CreateAndWrapWasmModule(aCx,
|
||||
bytecodeFile,
|
||||
compiledFile,
|
||||
file,
|
||||
data,
|
||||
&result))) {
|
||||
return nullptr;
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace JS {
|
||||
struct WasmModule;
|
||||
} // namespace JS
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -36,6 +40,7 @@ struct StructuredCloneFile
|
|||
|
||||
RefPtr<Blob> mBlob;
|
||||
RefPtr<IDBMutableFile> mMutableFile;
|
||||
RefPtr<JS::WasmModule> mWasmModule;
|
||||
RefPtr<FileInfo> mFileInfo;
|
||||
FileType mType;
|
||||
// This is currently specific to eWasmCompiled files.
|
||||
|
|
|
@ -106,12 +106,51 @@ union RequestResponse
|
|||
IndexCountResponse;
|
||||
};
|
||||
|
||||
struct WasmModulePreprocessInfo
|
||||
{
|
||||
SerializedStructuredCloneFile[] files;
|
||||
};
|
||||
|
||||
struct ObjectStoreGetPreprocessParams
|
||||
{
|
||||
WasmModulePreprocessInfo preprocessInfo;
|
||||
};
|
||||
|
||||
union PreprocessParams
|
||||
{
|
||||
ObjectStoreGetPreprocessParams;
|
||||
};
|
||||
|
||||
struct ObjectStoreGetPreprocessResponse
|
||||
{
|
||||
};
|
||||
|
||||
// The nsresult is used if an error occurs for any preprocess request type.
|
||||
// The specific response types are sent on success.
|
||||
union PreprocessResponse
|
||||
{
|
||||
nsresult;
|
||||
ObjectStoreGetPreprocessResponse;
|
||||
};
|
||||
|
||||
protocol PBackgroundIDBRequest
|
||||
{
|
||||
manager PBackgroundIDBTransaction or PBackgroundIDBVersionChangeTransaction;
|
||||
|
||||
parent:
|
||||
async Continue(PreprocessResponse response);
|
||||
|
||||
child:
|
||||
async __delete__(RequestResponse response);
|
||||
|
||||
// Preprocess is used in cases where response processing needs to do something
|
||||
// asynchronous off of the child actor's thread before returning the actual
|
||||
// result to user code. This is necessary because RequestResponse processing
|
||||
// occurs in __delete__ and the PBackgroundIDBRequest implementations'
|
||||
// life-cycles are controlled by IPC and are not otherwise reference counted.
|
||||
// By introducing the (optional) Preprocess/Continue steps reference counting
|
||||
// or the introduction of additional runnables are avoided.
|
||||
async Preprocess(PreprocessParams params);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
|
@ -85,17 +85,17 @@ function getNullFile(name, size)
|
|||
return getFile(name, "binary/null", getView(size));
|
||||
}
|
||||
|
||||
function isWasmSupported()
|
||||
// This needs to be async to make it available on workers too.
|
||||
function getWasmBinary(text)
|
||||
{
|
||||
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
return testingFunctions.wasmIsSupported();
|
||||
let binary = getWasmBinarySync(text);
|
||||
SimpleTest.executeSoon(function() {
|
||||
testGenerator.send(binary);
|
||||
});
|
||||
}
|
||||
|
||||
function getWasmModule(text)
|
||||
function getWasmModule(binary)
|
||||
{
|
||||
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
let wasmTextToBinary = SpecialPowers.unwrap(testingFunctions.wasmTextToBinary);
|
||||
let binary = wasmTextToBinary(text);
|
||||
let module = new WebAssembly.Module(binary);
|
||||
return module;
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ function verifyWasmModule(module1, module2)
|
|||
let exp2 = wasmExtractCode(module2);
|
||||
let code1 = exp1.code;
|
||||
let code2 = exp2.code;
|
||||
ok(code1 instanceof Uint8Array, "Instance of Uint8Array");
|
||||
todo(code1 instanceof Uint8Array, "Instance of Uint8Array");
|
||||
ok(code1.length == code2.length, "Correct length");
|
||||
verifyBuffers(code1, code2);
|
||||
continueToNextStep();
|
||||
|
|
|
@ -76,7 +76,8 @@ function testHarnessSteps() {
|
|||
["dom.indexedDB.testing", true],
|
||||
["dom.indexedDB.experimental", true],
|
||||
["dom.archivereader.enabled", true],
|
||||
["dom.workers.latestJSVersion", true]
|
||||
["dom.workers.latestJSVersion", true],
|
||||
["javascript.options.wasm", true]
|
||||
]
|
||||
},
|
||||
nextTestHarnessStep
|
||||
|
@ -145,7 +146,7 @@ function testHarnessSteps() {
|
|||
break;
|
||||
|
||||
case "loaded":
|
||||
worker.postMessage({ op: "start" });
|
||||
worker.postMessage({ op: "start", wasmSupported: isWasmSupported() });
|
||||
break;
|
||||
|
||||
case "done":
|
||||
|
@ -163,6 +164,11 @@ function testHarnessSteps() {
|
|||
});
|
||||
break;
|
||||
|
||||
case "getWasmBinary":
|
||||
worker.postMessage({ op: "getWasmBinaryDone",
|
||||
wasmBinary: getWasmBinarySync(message.text) });
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(false,
|
||||
"Received a bad message from worker: " + JSON.stringify(message));
|
||||
|
@ -348,9 +354,25 @@ function scheduleGC()
|
|||
SpecialPowers.exactGC(continueToNextStep);
|
||||
}
|
||||
|
||||
function isWasmSupported()
|
||||
{
|
||||
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
return testingFunctions.wasmIsSupported();
|
||||
}
|
||||
|
||||
function getWasmBinarySync(text)
|
||||
{
|
||||
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
let wasmTextToBinary = SpecialPowers.unwrap(testingFunctions.wasmTextToBinary);
|
||||
let binary = wasmTextToBinary(text);
|
||||
return binary;
|
||||
}
|
||||
|
||||
function workerScript() {
|
||||
"use strict";
|
||||
|
||||
self.wasmSupported = false;
|
||||
|
||||
self.repr = function(_thing_) {
|
||||
if (typeof(_thing_) == "undefined") {
|
||||
return "undefined";
|
||||
|
@ -538,6 +560,28 @@ function workerScript() {
|
|||
return true;
|
||||
};
|
||||
|
||||
self.isWasmSupported = function() {
|
||||
return self.wasmSupported;
|
||||
}
|
||||
|
||||
self.getWasmBinarySync = function(_text_) {
|
||||
self.ok(false, "This can't be used on workers");
|
||||
}
|
||||
|
||||
self.getWasmBinary = function(_text_) {
|
||||
self.postMessage({ op: "getWasmBinary", text: _text_ });
|
||||
}
|
||||
|
||||
self.getWasmModule = function(_binary_) {
|
||||
let module = new WebAssembly.Module(_binary_);
|
||||
return module;
|
||||
}
|
||||
|
||||
self.verifyWasmModule = function(_module) {
|
||||
self.todo(false, "Need a verifyWasmModule implementation on workers");
|
||||
self.continueToNextStep();
|
||||
}
|
||||
|
||||
self.onmessage = function(_event_) {
|
||||
let message = _event_.data;
|
||||
switch (message.op) {
|
||||
|
@ -548,6 +592,7 @@ function workerScript() {
|
|||
break;
|
||||
|
||||
case "start":
|
||||
self.wasmSupported = message.wasmSupported;
|
||||
executeSoon(function() {
|
||||
info("Worker: starting tests");
|
||||
testGenerator.next();
|
||||
|
@ -561,6 +606,11 @@ function workerScript() {
|
|||
}
|
||||
break;
|
||||
|
||||
case "getWasmBinaryDone":
|
||||
info("Worker: get wasm binary done");
|
||||
testGenerator.send(message.wasmBinary);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Received a bad message from parent: " +
|
||||
JSON.stringify(message));
|
||||
|
|
|
@ -392,7 +392,6 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
|||
[test_view_put_get_values.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_wasm_put_get_values.html]
|
||||
#skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
skip-if = true
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_serviceworker.html]
|
||||
skip-if = buildapp == 'b2g'
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var disableWorkerTest = "Need a way to set temporary prefs from a worker";
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
|
@ -16,19 +14,16 @@ function testSteps()
|
|||
|
||||
const wasmData = { key: 1, wasm: null };
|
||||
|
||||
if (this.window) {
|
||||
SpecialPowers.pushPrefEnv({ "set": [["javascript.options.wasm", true]] },
|
||||
continueToNextStep);
|
||||
yield undefined;
|
||||
} else {
|
||||
enableWasm();
|
||||
}
|
||||
|
||||
if (!isWasmSupported()) {
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
getWasmBinary('(module (func (nop)))');
|
||||
let binary = yield undefined;
|
||||
|
||||
wasmData.wasm = getWasmModule(binary);
|
||||
|
||||
info("Opening database");
|
||||
|
||||
let request = indexedDB.open(name);
|
||||
|
@ -53,8 +48,6 @@ function testSteps()
|
|||
|
||||
info("Storing wasm");
|
||||
|
||||
wasmData.wasm = getWasmModule('(module (func (nop)))');
|
||||
|
||||
let objectStore = db.transaction([objectStoreName], "readwrite")
|
||||
.objectStore(objectStoreName);
|
||||
request = objectStore.add(wasmData.wasm, wasmData.key);
|
||||
|
|
|
@ -50,6 +50,7 @@ if (!this.runTest) {
|
|||
|
||||
enableTesting();
|
||||
enableExperimental();
|
||||
enableWasm();
|
||||
}
|
||||
|
||||
Cu.importGlobalProperties(["indexedDB", "Blob", "File", "FileReader"]);
|
||||
|
@ -62,6 +63,7 @@ if (!this.runTest) {
|
|||
function finishTest()
|
||||
{
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
resetWasm();
|
||||
resetExperimental();
|
||||
resetTesting();
|
||||
|
||||
|
@ -214,6 +216,11 @@ function enableWasm()
|
|||
SpecialPowers.setBoolPref("javascript.options.wasm", true);
|
||||
}
|
||||
|
||||
function resetWasm()
|
||||
{
|
||||
SpecialPowers.clearUserPref("javascript.options.wasm");
|
||||
}
|
||||
|
||||
function gc()
|
||||
{
|
||||
Cu.forceGC();
|
||||
|
@ -374,10 +381,23 @@ function isWasmSupported()
|
|||
return testingFunctions.wasmIsSupported();
|
||||
}
|
||||
|
||||
function getWasmModule(text)
|
||||
function getWasmBinarySync(text)
|
||||
{
|
||||
let testingFunctions = Cu.getJSTestingFunctions();
|
||||
let binary = testingFunctions.wasmTextToBinary(text);
|
||||
return binary;
|
||||
}
|
||||
|
||||
function getWasmBinary(text)
|
||||
{
|
||||
let binary = getWasmBinarySync(text);
|
||||
executeSoon(function() {
|
||||
testGenerator.send(binary);
|
||||
});
|
||||
}
|
||||
|
||||
function getWasmModule(binary)
|
||||
{
|
||||
let module = new WebAssembly.Module(binary);
|
||||
return module;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче