зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1264053 - MessagePort should support transferable objects in multi-e10s, r=sfink, r=smaug, r=jorendorff, r=janv
This commit is contained in:
Родитель
faa4e6f42c
Коммит
a183983968
|
@ -36,7 +36,7 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
|
|||
nsIDocument* aSourceDocument,
|
||||
bool aTrustedCaller)
|
||||
: StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
SameProcessSameThread),
|
||||
StructuredCloneScope::SameProcessSameThread),
|
||||
mSource(aSource),
|
||||
mCallerOrigin(aCallerOrigin),
|
||||
mTargetWindow(aTargetWindow),
|
||||
|
|
|
@ -146,9 +146,10 @@ const JSStructuredCloneCallbacks gCallbacks = {
|
|||
|
||||
// StructuredCloneHolderBase class
|
||||
|
||||
StructuredCloneHolderBase::StructuredCloneHolderBase()
|
||||
StructuredCloneHolderBase::StructuredCloneHolderBase(StructuredCloneScope aScope)
|
||||
: mStructuredCloneScope(aScope)
|
||||
#ifdef DEBUG
|
||||
: mClearCalled(false)
|
||||
, mClearCalled(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
|
@ -184,7 +185,7 @@ StructuredCloneHolderBase::Write(JSContext* aCx,
|
|||
MOZ_ASSERT(!mBuffer, "Double Write is not allowed");
|
||||
MOZ_ASSERT(!mClearCalled, "This method cannot be called after Clear.");
|
||||
|
||||
mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this);
|
||||
mBuffer = new JSAutoStructuredCloneBuffer(mStructuredCloneScope, &gCallbacks, this);
|
||||
|
||||
if (!mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this)) {
|
||||
mBuffer = nullptr;
|
||||
|
@ -242,10 +243,10 @@ StructuredCloneHolderBase::CustomFreeTransferHandler(uint32_t aTag,
|
|||
|
||||
StructuredCloneHolder::StructuredCloneHolder(CloningSupport aSupportsCloning,
|
||||
TransferringSupport aSupportsTransferring,
|
||||
ContextSupport aContext)
|
||||
: mSupportsCloning(aSupportsCloning == CloningSupported)
|
||||
StructuredCloneScope aScope)
|
||||
: StructuredCloneHolderBase(aScope)
|
||||
, mSupportsCloning(aSupportsCloning == CloningSupported)
|
||||
, mSupportsTransferring(aSupportsTransferring == TransferringSupported)
|
||||
, mSupportedContext(aContext)
|
||||
, mParent(nullptr)
|
||||
#ifdef DEBUG
|
||||
, mCreationThread(NS_GetCurrentThread())
|
||||
|
@ -272,7 +273,7 @@ StructuredCloneHolder::Write(JSContext* aCx,
|
|||
JS::Handle<JS::Value> aTransfer,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread,
|
||||
MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
|
||||
mCreationThread == NS_GetCurrentThread());
|
||||
|
||||
if (!StructuredCloneHolderBase::Write(aCx, aValue, aTransfer)) {
|
||||
|
@ -280,7 +281,7 @@ StructuredCloneHolder::Write(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
if (mSupportedContext != SameProcessSameThread) {
|
||||
if (mStructuredCloneScope != StructuredCloneScope::SameProcessSameThread) {
|
||||
for (uint32_t i = 0, len = mBlobImplArray.Length(); i < len; ++i) {
|
||||
if (!mBlobImplArray[i]->MayBeClonedToOtherThreads()) {
|
||||
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
|
@ -296,7 +297,7 @@ StructuredCloneHolder::Read(nsISupports* aParent,
|
|||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread,
|
||||
MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
|
||||
mCreationThread == NS_GetCurrentThread());
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
|
@ -337,7 +338,7 @@ StructuredCloneHolder::ReadFromBuffer(nsISupports* aParent,
|
|||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread,
|
||||
MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
|
||||
mCreationThread == NS_GetCurrentThread());
|
||||
|
||||
MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write().");
|
||||
|
@ -347,7 +348,8 @@ StructuredCloneHolder::ReadFromBuffer(nsISupports* aParent,
|
|||
mParent = aParent;
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength, aAlgorithmVersion,
|
||||
aValue, &gCallbacks, this)) {
|
||||
mStructuredCloneScope, aValue, &gCallbacks,
|
||||
this)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
|
@ -357,7 +359,7 @@ void
|
|||
StructuredCloneHolder::MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread,
|
||||
MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
|
||||
mCreationThread == NS_GetCurrentThread());
|
||||
|
||||
MOZ_ASSERT(mBuffer, "MoveBuffer() cannot be called without a Write().");
|
||||
|
@ -1041,8 +1043,8 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
|
|||
if (aValue.IsDirectory()) {
|
||||
Directory* directory = aValue.GetAsDirectory();
|
||||
|
||||
if (closure->mHolder->SupportedContext() !=
|
||||
StructuredCloneHolder::SameProcessSameThread &&
|
||||
if (closure->mHolder->CloneScope() !=
|
||||
StructuredCloneHolder::StructuredCloneScope::SameProcessSameThread &&
|
||||
!directory->ClonableToDifferentThreadOrProcess()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1092,8 +1094,8 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_IMAGEBITMAP) {
|
||||
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread);
|
||||
MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
|
||||
|
||||
// Get the current global object.
|
||||
// This can be null.
|
||||
|
@ -1127,7 +1129,7 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
|
|||
{
|
||||
Directory* directory = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Directory, aObj, directory))) {
|
||||
if (mSupportedContext != SameProcessSameThread &&
|
||||
if (mStructuredCloneScope != StructuredCloneScope::SameProcessSameThread &&
|
||||
!directory->ClonableToDifferentThreadOrProcess()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1153,8 +1155,8 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
|
|||
}
|
||||
|
||||
// See if this is an ImageBitmap object.
|
||||
if (mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread) {
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) {
|
||||
ImageBitmap* imageBitmap = nullptr;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) {
|
||||
return ImageBitmap::WriteStructuredClone(aWriter,
|
||||
|
@ -1203,8 +1205,8 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_CANVAS) {
|
||||
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread);
|
||||
MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
|
||||
MOZ_ASSERT(aContent);
|
||||
OffscreenCanvasCloneData* data =
|
||||
static_cast<OffscreenCanvasCloneData*>(aContent);
|
||||
|
@ -1223,8 +1225,8 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_IMAGEBITMAP) {
|
||||
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread);
|
||||
MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
|
||||
MOZ_ASSERT(aContent);
|
||||
ImageBitmapCloneData* data =
|
||||
static_cast<ImageBitmapCloneData*>(aContent);
|
||||
|
@ -1274,8 +1276,8 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread) {
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) {
|
||||
OffscreenCanvas* canvas = nullptr;
|
||||
rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -1327,8 +1329,8 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
|
|||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_CANVAS) {
|
||||
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread);
|
||||
MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
|
||||
MOZ_ASSERT(aContent);
|
||||
OffscreenCanvasCloneData* data =
|
||||
static_cast<OffscreenCanvasCloneData*>(aContent);
|
||||
|
@ -1337,8 +1339,8 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
|
|||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_IMAGEBITMAP) {
|
||||
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
|
||||
mSupportedContext == SameProcessDifferentThread);
|
||||
MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
|
||||
MOZ_ASSERT(aContent);
|
||||
ImageBitmapCloneData* data =
|
||||
static_cast<ImageBitmapCloneData*>(aContent);
|
||||
|
|
|
@ -31,7 +31,9 @@ namespace dom {
|
|||
class StructuredCloneHolderBase
|
||||
{
|
||||
public:
|
||||
StructuredCloneHolderBase();
|
||||
typedef JS::StructuredCloneScope StructuredCloneScope;
|
||||
|
||||
StructuredCloneHolderBase(StructuredCloneScope aScope = StructuredCloneScope::SameProcessSameThread);
|
||||
virtual ~StructuredCloneHolderBase();
|
||||
|
||||
// These methods should be implemented in order to clone data.
|
||||
|
@ -115,6 +117,8 @@ public:
|
|||
protected:
|
||||
nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer;
|
||||
|
||||
StructuredCloneScope mStructuredCloneScope;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mClearCalled;
|
||||
#endif
|
||||
|
@ -139,24 +143,17 @@ public:
|
|||
TransferringNotSupported
|
||||
};
|
||||
|
||||
enum ContextSupport
|
||||
{
|
||||
SameProcessSameThread,
|
||||
SameProcessDifferentThread,
|
||||
DifferentProcess
|
||||
};
|
||||
|
||||
// If cloning is supported, this object will clone objects such as Blobs,
|
||||
// FileList, ImageData, etc.
|
||||
// If transferring is supported, we will transfer MessagePorts and in the
|
||||
// future other transferrable objects.
|
||||
// The ContextSupport is useful to know where the cloned/transferred data can
|
||||
// be read and written. Additional checks about the nature of the objects
|
||||
// will be done based on this context value because not all the objects can
|
||||
// be sent between threads or processes.
|
||||
// The StructuredCloneScope is useful to know where the cloned/transferred
|
||||
// data can be read and written. Additional checks about the nature of the
|
||||
// objects will be done based on this scope value because not all the
|
||||
// objects can be sent between threads or processes.
|
||||
explicit StructuredCloneHolder(CloningSupport aSupportsCloning,
|
||||
TransferringSupport aSupportsTransferring,
|
||||
ContextSupport aContextSupport);
|
||||
StructuredCloneScope aStructuredCloneScope);
|
||||
virtual ~StructuredCloneHolder();
|
||||
|
||||
// Normally you should just use Write() and Read().
|
||||
|
@ -194,9 +191,9 @@ public:
|
|||
return mBlobImplArray;
|
||||
}
|
||||
|
||||
ContextSupport SupportedContext() const
|
||||
StructuredCloneScope CloneScope() const
|
||||
{
|
||||
return mSupportedContext;
|
||||
return mStructuredCloneScope;
|
||||
}
|
||||
|
||||
// The parent object is set internally just during the Read(). This method
|
||||
|
@ -294,7 +291,6 @@ protected:
|
|||
|
||||
bool mSupportsCloning;
|
||||
bool mSupportsTransferring;
|
||||
ContextSupport mSupportedContext;
|
||||
|
||||
// Used for cloning blobs in the structured cloning algorithm.
|
||||
nsTArray<RefPtr<BlobImpl>> mBlobImplArray;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
BroadcastChannelMessage()
|
||||
: StructuredCloneHolder(CloningSupported, TransferringNotSupported,
|
||||
DifferentProcess)
|
||||
StructuredCloneScope::DifferentProcess)
|
||||
{}
|
||||
|
||||
private:
|
||||
|
|
|
@ -149,11 +149,11 @@ class VersionChangeTransaction;
|
|||
|
||||
// If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
|
||||
// schema version.
|
||||
static_assert(JS_STRUCTURED_CLONE_VERSION == 6,
|
||||
static_assert(JS_STRUCTURED_CLONE_VERSION == 7,
|
||||
"Need to update the major schema version.");
|
||||
|
||||
// Major schema version. Bump for almost everything.
|
||||
const uint32_t kMajorSchemaVersion = 23;
|
||||
const uint32_t kMajorSchemaVersion = 24;
|
||||
|
||||
// Minor schema version. Should almost always be 0 (maybe bump on release
|
||||
// branches if we have to).
|
||||
|
@ -4101,6 +4101,19 @@ UpgradeSchemaFrom22_0To23_0(mozIStorageConnection* aConnection,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UpgradeSchemaFrom23_0To24_0(mozIStorageConnection* aConnection)
|
||||
{
|
||||
// The only change between 23 and 24 was a different structured clone format,
|
||||
// but it's backwards-compatible.
|
||||
nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(24, 0));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
|
@ -4607,7 +4620,7 @@ CreateStorageConnection(nsIFile* aDBFile,
|
|||
}
|
||||
} else {
|
||||
// This logic needs to change next time we change the schema!
|
||||
static_assert(kSQLiteSchemaVersion == int32_t((23 << 4) + 0),
|
||||
static_assert(kSQLiteSchemaVersion == int32_t((24 << 4) + 0),
|
||||
"Upgrade function needed due to schema version increase.");
|
||||
|
||||
while (schemaVersion != kSQLiteSchemaVersion) {
|
||||
|
@ -4651,6 +4664,8 @@ CreateStorageConnection(nsIFile* aDBFile,
|
|||
rv = UpgradeSchemaFrom21_0To22_0(connection);
|
||||
} else if (schemaVersion == MakeSchemaVersion(22, 0)) {
|
||||
rv = UpgradeSchemaFrom22_0To23_0(connection, aOrigin);
|
||||
} else if (schemaVersion == MakeSchemaVersion(23, 0)) {
|
||||
rv = UpgradeSchemaFrom23_0To24_0(connection);
|
||||
} else {
|
||||
IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
|
||||
"available!");
|
||||
|
|
|
@ -80,7 +80,9 @@ struct IDBObjectStore::StructuredCloneWriteInfo
|
|||
uint64_t mOffsetToKeyProp;
|
||||
|
||||
explicit StructuredCloneWriteInfo(IDBDatabase* aDatabase)
|
||||
: mDatabase(aDatabase)
|
||||
: mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
|
||||
nullptr)
|
||||
, mDatabase(aDatabase)
|
||||
, mOffsetToKeyProp(0)
|
||||
{
|
||||
MOZ_ASSERT(aDatabase);
|
||||
|
@ -1110,6 +1112,7 @@ IDBObjectStore::DeserializeValue(JSContext* aCx,
|
|||
// FIXME: Consider to use StructuredCloneHolder here and in other
|
||||
// deserializing methods.
|
||||
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
aValue, &callbacks, &aCloneReadInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1148,6 +1151,7 @@ IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
|
|||
};
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
aValue, &callbacks, &aCloneReadInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1191,6 +1195,7 @@ IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
|
|||
};
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
aValue, &callbacks, &aCloneReadInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ StructuredCloneFile::operator==(const StructuredCloneFile& aOther) const
|
|||
inline
|
||||
StructuredCloneReadInfo::StructuredCloneReadInfo()
|
||||
: mDatabase(nullptr)
|
||||
, mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
|
||||
nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
|
||||
}
|
||||
|
@ -56,6 +58,8 @@ StructuredCloneReadInfo::StructuredCloneReadInfo(
|
|||
SerializedStructuredCloneReadInfo&& aCloneReadInfo)
|
||||
: mData(Move(aCloneReadInfo.data()))
|
||||
, mDatabase(nullptr)
|
||||
, mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
|
||||
nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StructuredCloneReadInfo);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
StructuredCloneData()
|
||||
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
|
||||
StructuredCloneHolder::TransferringSupported,
|
||||
StructuredCloneHolder::DifferentProcess)
|
||||
StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
|
||||
, mExternalData(nullptr)
|
||||
, mExternalDataLength(0)
|
||||
{}
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
|
||||
SharedMessagePortMessage()
|
||||
: StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
DifferentProcess)
|
||||
StructuredCloneScope::DifferentProcess)
|
||||
{}
|
||||
|
||||
void Read(nsISupports* aParent,
|
||||
|
|
|
@ -93,7 +93,7 @@ class ServiceWorkerClientPostMessageRunnable final
|
|||
public:
|
||||
explicit ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId)
|
||||
: StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
SameProcessDifferentThread)
|
||||
StructuredCloneScope::SameProcessDifferentThread)
|
||||
, mWindowId(aWindowId)
|
||||
{}
|
||||
|
||||
|
|
|
@ -674,7 +674,7 @@ public:
|
|||
TargetAndBusyBehavior aBehavior)
|
||||
: WorkerRunnable(aWorkerPrivate, aBehavior)
|
||||
, StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
SameProcessDifferentThread)
|
||||
StructuredCloneScope::SameProcessDifferentThread)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
const nsAString& aStringBody)
|
||||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
|
||||
, StructuredCloneHolder(CloningSupported, TransferringNotSupported,
|
||||
SameProcessDifferentThread)
|
||||
StructuredCloneScope::SameProcessDifferentThread)
|
||||
, mStringBody(aStringBody)
|
||||
, mHasUploadListeners(false)
|
||||
{
|
||||
|
@ -502,7 +502,7 @@ public:
|
|||
JS::Handle<JSObject*> aScopeObj)
|
||||
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy),
|
||||
StructuredCloneHolder(CloningSupported, TransferringNotSupported,
|
||||
SameProcessDifferentThread),
|
||||
StructuredCloneScope::SameProcessDifferentThread),
|
||||
mType(aType), mResponse(JS::UndefinedValue()), mLoaded(aLoaded),
|
||||
mTotal(aTotal), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0),
|
||||
mReadyState(0), mUploadEvent(aUploadEvent), mProgressEvent(true),
|
||||
|
@ -515,7 +515,7 @@ public:
|
|||
JS::Handle<JSObject*> aScopeObj)
|
||||
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy),
|
||||
StructuredCloneHolder(CloningSupported, TransferringNotSupported,
|
||||
SameProcessDifferentThread),
|
||||
StructuredCloneScope::SameProcessDifferentThread),
|
||||
mType(aType), mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0),
|
||||
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
|
||||
mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0),
|
||||
|
|
|
@ -22,6 +22,13 @@ struct JSStructuredCloneWriter;
|
|||
// API for the HTML5 internal structured cloning algorithm.
|
||||
|
||||
namespace JS {
|
||||
|
||||
enum class StructuredCloneScope : uint32_t {
|
||||
SameProcessSameThread,
|
||||
SameProcessDifferentThread,
|
||||
DifferentProcess
|
||||
};
|
||||
|
||||
enum TransferableOwnership {
|
||||
/** Transferable data has not been filled in yet */
|
||||
SCTAG_TMO_UNFILLED = 0,
|
||||
|
@ -134,7 +141,7 @@ typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwne
|
|||
// Increment this when anything at all changes in the serialization format.
|
||||
// (Note that this does not need to be bumped for Transferable-only changes,
|
||||
// since they are never saved to persistent storage.)
|
||||
#define JS_STRUCTURED_CLONE_VERSION 6
|
||||
#define JS_STRUCTURED_CLONE_VERSION 7
|
||||
|
||||
struct JSStructuredCloneCallbacks {
|
||||
ReadStructuredCloneOp read;
|
||||
|
@ -148,6 +155,7 @@ struct JSStructuredCloneCallbacks {
|
|||
/** Note: if the *data contains transferable objects, it can be read only once. */
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t version,
|
||||
JS::StructuredCloneScope scope,
|
||||
JS::MutableHandleValue vp,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
|
||||
|
||||
|
@ -157,6 +165,7 @@ JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t ve
|
|||
*/
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp,
|
||||
JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks,
|
||||
void* closure, JS::HandleValue transferable);
|
||||
|
||||
|
@ -174,6 +183,7 @@ JS_StructuredClone(JSContext* cx, JS::HandleValue v, JS::MutableHandleValue vp,
|
|||
|
||||
/** RAII sugar for JS_WriteStructuredClone. */
|
||||
class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
|
||||
const JS::StructuredCloneScope scope_;
|
||||
uint64_t* data_;
|
||||
size_t nbytes_;
|
||||
uint32_t version_;
|
||||
|
@ -187,14 +197,9 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
|
|||
void* closure_;
|
||||
|
||||
public:
|
||||
JSAutoStructuredCloneBuffer()
|
||||
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
|
||||
ownTransferables_(NoTransferables),
|
||||
callbacks_(nullptr), closure_(nullptr)
|
||||
{}
|
||||
|
||||
JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks* callbacks, void* closure)
|
||||
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
|
||||
JSAutoStructuredCloneBuffer(JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* callbacks, void* closure)
|
||||
: scope_(scope), data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
|
||||
ownTransferables_(NoTransferables),
|
||||
callbacks_(callbacks), closure_(closure)
|
||||
{}
|
||||
|
|
|
@ -2212,7 +2212,7 @@ Serialize(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSAutoStructuredCloneBuffer clonebuf;
|
||||
JSAutoStructuredCloneBuffer clonebuf(JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
|
||||
if (!clonebuf.write(cx, args.get(0), args.get(1)))
|
||||
return false;
|
||||
|
||||
|
@ -2254,7 +2254,10 @@ Deserialize(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
RootedValue deserialized(cx);
|
||||
if (!JS_ReadStructuredClone(cx, obj->data(), obj->nbytes(),
|
||||
JS_STRUCTURED_CLONE_VERSION, &deserialized, nullptr, nullptr)) {
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
&deserialized, nullptr, nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
args.rval().set(deserialized);
|
||||
|
|
|
@ -126,7 +126,7 @@ bool TestCloneObject()
|
|||
{
|
||||
JS::RootedObject obj1(cx, CreateNewObject(8, 12));
|
||||
CHECK(obj1);
|
||||
JSAutoStructuredCloneBuffer cloned_buffer;
|
||||
JSAutoStructuredCloneBuffer cloned_buffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
|
||||
JS::RootedValue v1(cx, JS::ObjectValue(*obj1));
|
||||
CHECK(cloned_buffer.write(cx, v1, nullptr, nullptr));
|
||||
JS::RootedValue v2(cx);
|
||||
|
@ -164,7 +164,7 @@ bool TestTransferObject()
|
|||
CHECK(obj);
|
||||
JS::RootedValue transferable(cx, JS::ObjectValue(*obj));
|
||||
|
||||
JSAutoStructuredCloneBuffer cloned_buffer;
|
||||
JSAutoStructuredCloneBuffer cloned_buffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
|
||||
CHECK(cloned_buffer.write(cx, v1, transferable, nullptr, nullptr));
|
||||
JS::RootedValue v2(cx);
|
||||
CHECK(cloned_buffer.read(cx, &v2, nullptr, nullptr));
|
||||
|
|
|
@ -71,6 +71,7 @@ using JS::CanonicalizeNaN;
|
|||
enum StructuredDataType : uint32_t {
|
||||
/* Structured data types provided by the engine */
|
||||
SCTAG_FLOAT_MAX = 0xFFF00000,
|
||||
SCTAG_HEADER = 0xFFF10000,
|
||||
SCTAG_NULL = 0xFFFF0000,
|
||||
SCTAG_UNDEFINED,
|
||||
SCTAG_BOOLEAN,
|
||||
|
@ -226,9 +227,10 @@ class SCInput {
|
|||
|
||||
struct JSStructuredCloneReader {
|
||||
public:
|
||||
explicit JSStructuredCloneReader(SCInput& in, const JSStructuredCloneCallbacks* cb,
|
||||
explicit JSStructuredCloneReader(SCInput& in, JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* cb,
|
||||
void* cbClosure)
|
||||
: in(in), objs(in.context()), allObjs(in.context()),
|
||||
: in(in), scope(scope), objs(in.context()), allObjs(in.context()),
|
||||
callbacks(cb), closure(cbClosure) { }
|
||||
|
||||
SCInput& input() { return in; }
|
||||
|
@ -237,6 +239,7 @@ struct JSStructuredCloneReader {
|
|||
private:
|
||||
JSContext* context() { return in.context(); }
|
||||
|
||||
bool readHeader();
|
||||
bool readTransferMap();
|
||||
|
||||
template <typename CharT>
|
||||
|
@ -254,6 +257,8 @@ struct JSStructuredCloneReader {
|
|||
|
||||
SCInput& in;
|
||||
|
||||
JS::StructuredCloneScope scope;
|
||||
|
||||
// Stack of objects with properties remaining to be read.
|
||||
AutoValueVector objs;
|
||||
|
||||
|
@ -272,10 +277,11 @@ struct JSStructuredCloneReader {
|
|||
struct JSStructuredCloneWriter {
|
||||
public:
|
||||
explicit JSStructuredCloneWriter(JSContext* cx,
|
||||
JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* cb,
|
||||
void* cbClosure,
|
||||
Value tVal)
|
||||
: out(cx), objs(out.context()),
|
||||
: out(cx), scope(scope), objs(out.context()),
|
||||
counts(out.context()), entries(out.context()),
|
||||
memory(out.context()), callbacks(cb),
|
||||
closure(cbClosure), transferable(out.context(), tVal),
|
||||
|
@ -289,7 +295,7 @@ struct JSStructuredCloneWriter {
|
|||
ReportOutOfMemory(context());
|
||||
return false;
|
||||
}
|
||||
return parseTransferable() && writeTransferMap();
|
||||
return parseTransferable() && writeHeader() && writeTransferMap();
|
||||
}
|
||||
|
||||
bool write(HandleValue v);
|
||||
|
@ -306,6 +312,7 @@ struct JSStructuredCloneWriter {
|
|||
|
||||
JSContext* context() { return out.context(); }
|
||||
|
||||
bool writeHeader();
|
||||
bool writeTransferMap();
|
||||
|
||||
bool writeString(uint32_t tag, JSString* str);
|
||||
|
@ -329,6 +336,9 @@ struct JSStructuredCloneWriter {
|
|||
|
||||
SCOutput out;
|
||||
|
||||
// The (address space, thread) scope within which this clone is valid.
|
||||
JS::StructuredCloneScope scope;
|
||||
|
||||
// Vector of objects with properties remaining to be written.
|
||||
//
|
||||
// NB: These can span multiple compartments, so the compartment must be
|
||||
|
@ -411,19 +421,21 @@ ReportDataCloneError(JSContext* cx,
|
|||
|
||||
bool
|
||||
WriteStructuredClone(JSContext* cx, HandleValue v, uint64_t** bufp, size_t* nbytesp,
|
||||
JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* cb, void* cbClosure,
|
||||
Value transferable)
|
||||
{
|
||||
JSStructuredCloneWriter w(cx, cb, cbClosure, transferable);
|
||||
JSStructuredCloneWriter w(cx, scope, cb, cbClosure, transferable);
|
||||
return w.init() && w.write(v) && w.extractBuffer(bufp, nbytesp);
|
||||
}
|
||||
|
||||
bool
|
||||
ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, MutableHandleValue vp,
|
||||
ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes,
|
||||
JS::StructuredCloneScope scope, MutableHandleValue vp,
|
||||
const JSStructuredCloneCallbacks* cb, void* cbClosure)
|
||||
{
|
||||
SCInput in(cx, data, nbytes);
|
||||
JSStructuredCloneReader r(in, cb, cbClosure);
|
||||
JSStructuredCloneReader r(in, scope, cb, cbClosure);
|
||||
return r.read(vp);
|
||||
}
|
||||
|
||||
|
@ -1263,6 +1275,12 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
|
|||
return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneWriter::writeHeader()
|
||||
{
|
||||
return out.writePair(SCTAG_HEADER, (uint32_t)scope);
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneWriter::writeTransferMap()
|
||||
{
|
||||
|
@ -1307,6 +1325,8 @@ JSStructuredCloneWriter::transferOwnership()
|
|||
// grabbing out pointers from the transferables and stuffing them into the
|
||||
// transfer map.
|
||||
uint64_t* point = out.rawBuffer();
|
||||
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_HEADER);
|
||||
point++;
|
||||
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_HEADER);
|
||||
point++;
|
||||
MOZ_ASSERT(LittleEndian::readUint64(point) == transferableObjects.count());
|
||||
|
@ -1342,6 +1362,8 @@ JSStructuredCloneWriter::transferOwnership()
|
|||
// and malloc'd buffers, not asm.js-ified buffers.
|
||||
bool hasStealableContents = arrayBuffer->hasStealableContents() &&
|
||||
(arrayBuffer->isMapped() || arrayBuffer->hasMallocedContents());
|
||||
if (scope == JS::StructuredCloneScope::DifferentProcess)
|
||||
hasStealableContents = false;
|
||||
|
||||
ArrayBufferObject::BufferContents bufContents =
|
||||
ArrayBufferObject::stealContents(context(), arrayBuffer, hasStealableContents);
|
||||
|
@ -1896,6 +1918,29 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::readHeader()
|
||||
{
|
||||
uint32_t tag, data;
|
||||
if (!in.getPair(&tag, &data))
|
||||
return in.reportTruncated();
|
||||
|
||||
if (tag != SCTAG_HEADER) {
|
||||
// Old structured clone buffer. We must have read it from disk or
|
||||
// somewhere, so we can assume it's scope-compatible.
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(in.readPair(&tag, &data));
|
||||
if (data < uint32_t(scope)) {
|
||||
JS_ReportErrorNumber(context(), GetErrorMessage, nullptr,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "incompatible structured clone scope");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::readTransferMap()
|
||||
{
|
||||
|
@ -2071,6 +2116,9 @@ JSStructuredCloneReader::readSavedFrame(uint32_t principalsTag)
|
|||
bool
|
||||
JSStructuredCloneReader::read(MutableHandleValue vp)
|
||||
{
|
||||
if (!readHeader())
|
||||
return false;
|
||||
|
||||
if (!readTransferMap())
|
||||
return false;
|
||||
|
||||
|
@ -2178,7 +2226,8 @@ using namespace js;
|
|||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadStructuredClone(JSContext* cx, uint64_t* buf, size_t nbytes,
|
||||
uint32_t version, MutableHandleValue vp,
|
||||
uint32_t version, JS::StructuredCloneScope scope,
|
||||
MutableHandleValue vp,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks,
|
||||
void* closure)
|
||||
{
|
||||
|
@ -2190,11 +2239,12 @@ JS_ReadStructuredClone(JSContext* cx, uint64_t* buf, size_t nbytes,
|
|||
return false;
|
||||
}
|
||||
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks;
|
||||
return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
|
||||
return ReadStructuredClone(cx, buf, nbytes, scope, vp, callbacks, closure);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext* cx, HandleValue value, uint64_t** bufp, size_t* nbytesp,
|
||||
JS::StructuredCloneScope scope,
|
||||
const JSStructuredCloneCallbacks* optionalCallbacks,
|
||||
void* closure, HandleValue transferable)
|
||||
{
|
||||
|
@ -2203,7 +2253,7 @@ JS_WriteStructuredClone(JSContext* cx, HandleValue value, uint64_t** bufp, size_
|
|||
assertSameCompartment(cx, value);
|
||||
|
||||
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks;
|
||||
return WriteStructuredClone(cx, value, bufp, nbytesp, callbacks, closure, transferable);
|
||||
return WriteStructuredClone(cx, value, bufp, nbytesp, scope, callbacks, closure, transferable);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -2247,7 +2297,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
|
|||
|
||||
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks;
|
||||
|
||||
JSAutoStructuredCloneBuffer buf;
|
||||
JSAutoStructuredCloneBuffer buf(JS::StructuredCloneScope::SameProcessSameThread, callbacks, closure);
|
||||
{
|
||||
// If we use Maybe<AutoCompartment> here, G++ can't tell that the
|
||||
// destructor is only called when Maybe::construct was called, and
|
||||
|
@ -2266,6 +2316,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
|
|||
}
|
||||
|
||||
JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
|
||||
: scope_(other.scope_)
|
||||
{
|
||||
ownTransferables_ = other.ownTransferables_;
|
||||
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
|
||||
|
@ -2275,6 +2326,7 @@ JSAutoStructuredCloneBuffer&
|
|||
JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
|
||||
{
|
||||
MOZ_ASSERT(&other != this);
|
||||
MOZ_ASSERT(scope_ == other.scope_);
|
||||
clear();
|
||||
ownTransferables_ = other.ownTransferables_;
|
||||
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
|
||||
|
@ -2369,7 +2421,7 @@ JSAutoStructuredCloneBuffer::read(JSContext* cx, MutableHandleValue vp,
|
|||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(data_);
|
||||
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
|
||||
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, scope_, vp,
|
||||
optionalCallbacks, closure);
|
||||
}
|
||||
|
||||
|
@ -2390,6 +2442,7 @@ JSAutoStructuredCloneBuffer::write(JSContext* cx, HandleValue value,
|
|||
{
|
||||
clear();
|
||||
bool ok = JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
|
||||
scope_,
|
||||
optionalCallbacks, closure,
|
||||
transferable);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче