Bug 1264053 - MessagePort should support transferable objects in multi-e10s, r=sfink, r=smaug, r=jorendorff, r=janv

This commit is contained in:
Andrea Marchesini 2016-07-21 15:29:42 +02:00
Родитель faa4e6f42c
Коммит a183983968
16 изменённых файлов: 166 добавлений и 83 удалений

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

@ -36,7 +36,7 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
nsIDocument* aSourceDocument, nsIDocument* aSourceDocument,
bool aTrustedCaller) bool aTrustedCaller)
: StructuredCloneHolder(CloningSupported, TransferringSupported, : StructuredCloneHolder(CloningSupported, TransferringSupported,
SameProcessSameThread), StructuredCloneScope::SameProcessSameThread),
mSource(aSource), mSource(aSource),
mCallerOrigin(aCallerOrigin), mCallerOrigin(aCallerOrigin),
mTargetWindow(aTargetWindow), mTargetWindow(aTargetWindow),

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

@ -146,9 +146,10 @@ const JSStructuredCloneCallbacks gCallbacks = {
// StructuredCloneHolderBase class // StructuredCloneHolderBase class
StructuredCloneHolderBase::StructuredCloneHolderBase() StructuredCloneHolderBase::StructuredCloneHolderBase(StructuredCloneScope aScope)
: mStructuredCloneScope(aScope)
#ifdef DEBUG #ifdef DEBUG
: mClearCalled(false) , mClearCalled(false)
#endif #endif
{} {}
@ -184,7 +185,7 @@ StructuredCloneHolderBase::Write(JSContext* aCx,
MOZ_ASSERT(!mBuffer, "Double Write is not allowed"); MOZ_ASSERT(!mBuffer, "Double Write is not allowed");
MOZ_ASSERT(!mClearCalled, "This method cannot be called after Clear."); 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)) { if (!mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this)) {
mBuffer = nullptr; mBuffer = nullptr;
@ -242,10 +243,10 @@ StructuredCloneHolderBase::CustomFreeTransferHandler(uint32_t aTag,
StructuredCloneHolder::StructuredCloneHolder(CloningSupport aSupportsCloning, StructuredCloneHolder::StructuredCloneHolder(CloningSupport aSupportsCloning,
TransferringSupport aSupportsTransferring, TransferringSupport aSupportsTransferring,
ContextSupport aContext) StructuredCloneScope aScope)
: mSupportsCloning(aSupportsCloning == CloningSupported) : StructuredCloneHolderBase(aScope)
, mSupportsCloning(aSupportsCloning == CloningSupported)
, mSupportsTransferring(aSupportsTransferring == TransferringSupported) , mSupportsTransferring(aSupportsTransferring == TransferringSupported)
, mSupportedContext(aContext)
, mParent(nullptr) , mParent(nullptr)
#ifdef DEBUG #ifdef DEBUG
, mCreationThread(NS_GetCurrentThread()) , mCreationThread(NS_GetCurrentThread())
@ -272,7 +273,7 @@ StructuredCloneHolder::Write(JSContext* aCx,
JS::Handle<JS::Value> aTransfer, JS::Handle<JS::Value> aTransfer,
ErrorResult& aRv) ErrorResult& aRv)
{ {
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread, MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
mCreationThread == NS_GetCurrentThread()); mCreationThread == NS_GetCurrentThread());
if (!StructuredCloneHolderBase::Write(aCx, aValue, aTransfer)) { if (!StructuredCloneHolderBase::Write(aCx, aValue, aTransfer)) {
@ -280,7 +281,7 @@ StructuredCloneHolder::Write(JSContext* aCx,
return; return;
} }
if (mSupportedContext != SameProcessSameThread) { if (mStructuredCloneScope != StructuredCloneScope::SameProcessSameThread) {
for (uint32_t i = 0, len = mBlobImplArray.Length(); i < len; ++i) { for (uint32_t i = 0, len = mBlobImplArray.Length(); i < len; ++i) {
if (!mBlobImplArray[i]->MayBeClonedToOtherThreads()) { if (!mBlobImplArray[i]->MayBeClonedToOtherThreads()) {
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
@ -296,7 +297,7 @@ StructuredCloneHolder::Read(nsISupports* aParent,
JS::MutableHandle<JS::Value> aValue, JS::MutableHandle<JS::Value> aValue,
ErrorResult& aRv) ErrorResult& aRv)
{ {
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread, MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
mCreationThread == NS_GetCurrentThread()); mCreationThread == NS_GetCurrentThread());
MOZ_ASSERT(aParent); MOZ_ASSERT(aParent);
@ -337,7 +338,7 @@ StructuredCloneHolder::ReadFromBuffer(nsISupports* aParent,
JS::MutableHandle<JS::Value> aValue, JS::MutableHandle<JS::Value> aValue,
ErrorResult& aRv) ErrorResult& aRv)
{ {
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread, MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
mCreationThread == NS_GetCurrentThread()); mCreationThread == NS_GetCurrentThread());
MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write()."); MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write().");
@ -347,7 +348,8 @@ StructuredCloneHolder::ReadFromBuffer(nsISupports* aParent,
mParent = aParent; mParent = aParent;
if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength, aAlgorithmVersion, if (!JS_ReadStructuredClone(aCx, aBuffer, aBufferLength, aAlgorithmVersion,
aValue, &gCallbacks, this)) { mStructuredCloneScope, aValue, &gCallbacks,
this)) {
JS_ClearPendingException(aCx); JS_ClearPendingException(aCx);
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
} }
@ -357,7 +359,7 @@ void
StructuredCloneHolder::MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray, StructuredCloneHolder::MoveBufferDataToArray(FallibleTArray<uint8_t>& aArray,
ErrorResult& aRv) ErrorResult& aRv)
{ {
MOZ_ASSERT_IF(mSupportedContext == SameProcessSameThread, MOZ_ASSERT_IF(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
mCreationThread == NS_GetCurrentThread()); mCreationThread == NS_GetCurrentThread());
MOZ_ASSERT(mBuffer, "MoveBuffer() cannot be called without a Write()."); MOZ_ASSERT(mBuffer, "MoveBuffer() cannot be called without a Write().");
@ -1041,8 +1043,8 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
if (aValue.IsDirectory()) { if (aValue.IsDirectory()) {
Directory* directory = aValue.GetAsDirectory(); Directory* directory = aValue.GetAsDirectory();
if (closure->mHolder->SupportedContext() != if (closure->mHolder->CloneScope() !=
StructuredCloneHolder::SameProcessSameThread && StructuredCloneHolder::StructuredCloneScope::SameProcessSameThread &&
!directory->ClonableToDifferentThreadOrProcess()) { !directory->ClonableToDifferentThreadOrProcess()) {
return false; return false;
} }
@ -1092,8 +1094,8 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
} }
if (aTag == SCTAG_DOM_IMAGEBITMAP) { if (aTag == SCTAG_DOM_IMAGEBITMAP) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread || MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread); mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
// Get the current global object. // Get the current global object.
// This can be null. // This can be null.
@ -1127,7 +1129,7 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
{ {
Directory* directory = nullptr; Directory* directory = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Directory, aObj, directory))) { if (NS_SUCCEEDED(UNWRAP_OBJECT(Directory, aObj, directory))) {
if (mSupportedContext != SameProcessSameThread && if (mStructuredCloneScope != StructuredCloneScope::SameProcessSameThread &&
!directory->ClonableToDifferentThreadOrProcess()) { !directory->ClonableToDifferentThreadOrProcess()) {
return false; return false;
} }
@ -1153,8 +1155,8 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
} }
// See if this is an ImageBitmap object. // See if this is an ImageBitmap object.
if (mSupportedContext == SameProcessSameThread || if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread) { mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) {
ImageBitmap* imageBitmap = nullptr; ImageBitmap* imageBitmap = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) { if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) {
return ImageBitmap::WriteStructuredClone(aWriter, return ImageBitmap::WriteStructuredClone(aWriter,
@ -1203,8 +1205,8 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
} }
if (aTag == SCTAG_DOM_CANVAS) { if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread || MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread); mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
MOZ_ASSERT(aContent); MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data = OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent); static_cast<OffscreenCanvasCloneData*>(aContent);
@ -1223,8 +1225,8 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
} }
if (aTag == SCTAG_DOM_IMAGEBITMAP) { if (aTag == SCTAG_DOM_IMAGEBITMAP) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread || MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread); mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
MOZ_ASSERT(aContent); MOZ_ASSERT(aContent);
ImageBitmapCloneData* data = ImageBitmapCloneData* data =
static_cast<ImageBitmapCloneData*>(aContent); static_cast<ImageBitmapCloneData*>(aContent);
@ -1274,8 +1276,8 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
return true; return true;
} }
if (mSupportedContext == SameProcessSameThread || if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread) { mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) {
OffscreenCanvas* canvas = nullptr; OffscreenCanvas* canvas = nullptr;
rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas); rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
@ -1327,8 +1329,8 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
} }
if (aTag == SCTAG_DOM_CANVAS) { if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread || MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread); mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
MOZ_ASSERT(aContent); MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data = OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent); static_cast<OffscreenCanvasCloneData*>(aContent);
@ -1337,8 +1339,8 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
} }
if (aTag == SCTAG_DOM_IMAGEBITMAP) { if (aTag == SCTAG_DOM_IMAGEBITMAP) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread || MOZ_ASSERT(mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread); mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread);
MOZ_ASSERT(aContent); MOZ_ASSERT(aContent);
ImageBitmapCloneData* data = ImageBitmapCloneData* data =
static_cast<ImageBitmapCloneData*>(aContent); static_cast<ImageBitmapCloneData*>(aContent);

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

@ -31,7 +31,9 @@ namespace dom {
class StructuredCloneHolderBase class StructuredCloneHolderBase
{ {
public: public:
StructuredCloneHolderBase(); typedef JS::StructuredCloneScope StructuredCloneScope;
StructuredCloneHolderBase(StructuredCloneScope aScope = StructuredCloneScope::SameProcessSameThread);
virtual ~StructuredCloneHolderBase(); virtual ~StructuredCloneHolderBase();
// These methods should be implemented in order to clone data. // These methods should be implemented in order to clone data.
@ -115,6 +117,8 @@ public:
protected: protected:
nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer; nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer;
StructuredCloneScope mStructuredCloneScope;
#ifdef DEBUG #ifdef DEBUG
bool mClearCalled; bool mClearCalled;
#endif #endif
@ -139,24 +143,17 @@ public:
TransferringNotSupported TransferringNotSupported
}; };
enum ContextSupport
{
SameProcessSameThread,
SameProcessDifferentThread,
DifferentProcess
};
// If cloning is supported, this object will clone objects such as Blobs, // If cloning is supported, this object will clone objects such as Blobs,
// FileList, ImageData, etc. // FileList, ImageData, etc.
// If transferring is supported, we will transfer MessagePorts and in the // If transferring is supported, we will transfer MessagePorts and in the
// future other transferrable objects. // future other transferrable objects.
// The ContextSupport is useful to know where the cloned/transferred data can // The StructuredCloneScope is useful to know where the cloned/transferred
// be read and written. Additional checks about the nature of the objects // data can be read and written. Additional checks about the nature of the
// will be done based on this context value because not all the objects can // objects will be done based on this scope value because not all the
// be sent between threads or processes. // objects can be sent between threads or processes.
explicit StructuredCloneHolder(CloningSupport aSupportsCloning, explicit StructuredCloneHolder(CloningSupport aSupportsCloning,
TransferringSupport aSupportsTransferring, TransferringSupport aSupportsTransferring,
ContextSupport aContextSupport); StructuredCloneScope aStructuredCloneScope);
virtual ~StructuredCloneHolder(); virtual ~StructuredCloneHolder();
// Normally you should just use Write() and Read(). // Normally you should just use Write() and Read().
@ -194,9 +191,9 @@ public:
return mBlobImplArray; return mBlobImplArray;
} }
ContextSupport SupportedContext() const StructuredCloneScope CloneScope() const
{ {
return mSupportedContext; return mStructuredCloneScope;
} }
// The parent object is set internally just during the Read(). This method // The parent object is set internally just during the Read(). This method
@ -294,7 +291,6 @@ protected:
bool mSupportsCloning; bool mSupportsCloning;
bool mSupportsTransferring; bool mSupportsTransferring;
ContextSupport mSupportedContext;
// Used for cloning blobs in the structured cloning algorithm. // Used for cloning blobs in the structured cloning algorithm.
nsTArray<RefPtr<BlobImpl>> mBlobImplArray; nsTArray<RefPtr<BlobImpl>> mBlobImplArray;

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

@ -40,7 +40,7 @@ public:
BroadcastChannelMessage() BroadcastChannelMessage()
: StructuredCloneHolder(CloningSupported, TransferringNotSupported, : StructuredCloneHolder(CloningSupported, TransferringNotSupported,
DifferentProcess) StructuredCloneScope::DifferentProcess)
{} {}
private: private:

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

@ -149,11 +149,11 @@ class VersionChangeTransaction;
// If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major // If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
// schema version. // schema version.
static_assert(JS_STRUCTURED_CLONE_VERSION == 6, static_assert(JS_STRUCTURED_CLONE_VERSION == 7,
"Need to update the major schema version."); "Need to update the major schema version.");
// Major schema version. Bump for almost everything. // 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 // Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to). // branches if we have to).
@ -4101,6 +4101,19 @@ UpgradeSchemaFrom22_0To23_0(mozIStorageConnection* aConnection,
return NS_OK; 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 nsresult
GetDatabaseFileURL(nsIFile* aDatabaseFile, GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType, PersistenceType aPersistenceType,
@ -4607,7 +4620,7 @@ CreateStorageConnection(nsIFile* aDBFile,
} }
} else { } else {
// This logic needs to change next time we change the schema! // 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."); "Upgrade function needed due to schema version increase.");
while (schemaVersion != kSQLiteSchemaVersion) { while (schemaVersion != kSQLiteSchemaVersion) {
@ -4651,6 +4664,8 @@ CreateStorageConnection(nsIFile* aDBFile,
rv = UpgradeSchemaFrom21_0To22_0(connection); rv = UpgradeSchemaFrom21_0To22_0(connection);
} else if (schemaVersion == MakeSchemaVersion(22, 0)) { } else if (schemaVersion == MakeSchemaVersion(22, 0)) {
rv = UpgradeSchemaFrom22_0To23_0(connection, aOrigin); rv = UpgradeSchemaFrom22_0To23_0(connection, aOrigin);
} else if (schemaVersion == MakeSchemaVersion(23, 0)) {
rv = UpgradeSchemaFrom23_0To24_0(connection);
} else { } else {
IDB_WARNING("Unable to open IndexedDB database, no upgrade path is " IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
"available!"); "available!");

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

@ -80,7 +80,9 @@ struct IDBObjectStore::StructuredCloneWriteInfo
uint64_t mOffsetToKeyProp; uint64_t mOffsetToKeyProp;
explicit StructuredCloneWriteInfo(IDBDatabase* aDatabase) explicit StructuredCloneWriteInfo(IDBDatabase* aDatabase)
: mDatabase(aDatabase) : mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
nullptr)
, mDatabase(aDatabase)
, mOffsetToKeyProp(0) , mOffsetToKeyProp(0)
{ {
MOZ_ASSERT(aDatabase); MOZ_ASSERT(aDatabase);
@ -1110,6 +1112,7 @@ IDBObjectStore::DeserializeValue(JSContext* aCx,
// FIXME: Consider to use StructuredCloneHolder here and in other // FIXME: Consider to use StructuredCloneHolder here and in other
// deserializing methods. // deserializing methods.
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION, if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::SameProcessSameThread,
aValue, &callbacks, &aCloneReadInfo)) { aValue, &callbacks, &aCloneReadInfo)) {
return false; return false;
} }
@ -1148,6 +1151,7 @@ IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
}; };
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION, if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::SameProcessSameThread,
aValue, &callbacks, &aCloneReadInfo)) { aValue, &callbacks, &aCloneReadInfo)) {
return false; return false;
} }
@ -1191,6 +1195,7 @@ IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
}; };
if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION, if (!JS_ReadStructuredClone(aCx, data, dataLen, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::SameProcessSameThread,
aValue, &callbacks, &aCloneReadInfo)) { aValue, &callbacks, &aCloneReadInfo)) {
return false; return false;
} }

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

@ -47,6 +47,8 @@ StructuredCloneFile::operator==(const StructuredCloneFile& aOther) const
inline inline
StructuredCloneReadInfo::StructuredCloneReadInfo() StructuredCloneReadInfo::StructuredCloneReadInfo()
: mDatabase(nullptr) : mDatabase(nullptr)
, mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
nullptr)
{ {
MOZ_COUNT_CTOR(StructuredCloneReadInfo); MOZ_COUNT_CTOR(StructuredCloneReadInfo);
} }
@ -56,6 +58,8 @@ StructuredCloneReadInfo::StructuredCloneReadInfo(
SerializedStructuredCloneReadInfo&& aCloneReadInfo) SerializedStructuredCloneReadInfo&& aCloneReadInfo)
: mData(Move(aCloneReadInfo.data())) : mData(Move(aCloneReadInfo.data()))
, mDatabase(nullptr) , mDatabase(nullptr)
, mCloneBuffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr,
nullptr)
{ {
MOZ_COUNT_CTOR(StructuredCloneReadInfo); MOZ_COUNT_CTOR(StructuredCloneReadInfo);
} }

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

@ -80,7 +80,7 @@ public:
StructuredCloneData() StructuredCloneData()
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported, : StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
StructuredCloneHolder::TransferringSupported, StructuredCloneHolder::TransferringSupported,
StructuredCloneHolder::DifferentProcess) StructuredCloneHolder::StructuredCloneScope::DifferentProcess)
, mExternalData(nullptr) , mExternalData(nullptr)
, mExternalDataLength(0) , mExternalDataLength(0)
{} {}

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

@ -24,7 +24,7 @@ public:
SharedMessagePortMessage() SharedMessagePortMessage()
: StructuredCloneHolder(CloningSupported, TransferringSupported, : StructuredCloneHolder(CloningSupported, TransferringSupported,
DifferentProcess) StructuredCloneScope::DifferentProcess)
{} {}
void Read(nsISupports* aParent, void Read(nsISupports* aParent,

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

@ -93,7 +93,7 @@ class ServiceWorkerClientPostMessageRunnable final
public: public:
explicit ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId) explicit ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId)
: StructuredCloneHolder(CloningSupported, TransferringSupported, : StructuredCloneHolder(CloningSupported, TransferringSupported,
SameProcessDifferentThread) StructuredCloneScope::SameProcessDifferentThread)
, mWindowId(aWindowId) , mWindowId(aWindowId)
{} {}

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

@ -674,7 +674,7 @@ public:
TargetAndBusyBehavior aBehavior) TargetAndBusyBehavior aBehavior)
: WorkerRunnable(aWorkerPrivate, aBehavior) : WorkerRunnable(aWorkerPrivate, aBehavior)
, StructuredCloneHolder(CloningSupported, TransferringSupported, , StructuredCloneHolder(CloningSupported, TransferringSupported,
SameProcessDifferentThread) StructuredCloneScope::SameProcessDifferentThread)
{ {
} }

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

@ -244,7 +244,7 @@ public:
const nsAString& aStringBody) const nsAString& aStringBody)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy) : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
, StructuredCloneHolder(CloningSupported, TransferringNotSupported, , StructuredCloneHolder(CloningSupported, TransferringNotSupported,
SameProcessDifferentThread) StructuredCloneScope::SameProcessDifferentThread)
, mStringBody(aStringBody) , mStringBody(aStringBody)
, mHasUploadListeners(false) , mHasUploadListeners(false)
{ {
@ -502,7 +502,7 @@ public:
JS::Handle<JSObject*> aScopeObj) JS::Handle<JSObject*> aScopeObj)
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy),
StructuredCloneHolder(CloningSupported, TransferringNotSupported, StructuredCloneHolder(CloningSupported, TransferringNotSupported,
SameProcessDifferentThread), StructuredCloneScope::SameProcessDifferentThread),
mType(aType), mResponse(JS::UndefinedValue()), mLoaded(aLoaded), mType(aType), mResponse(JS::UndefinedValue()), mLoaded(aLoaded),
mTotal(aTotal), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mTotal(aTotal), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0),
mReadyState(0), mUploadEvent(aUploadEvent), mProgressEvent(true), mReadyState(0), mUploadEvent(aUploadEvent), mProgressEvent(true),
@ -515,7 +515,7 @@ public:
JS::Handle<JSObject*> aScopeObj) JS::Handle<JSObject*> aScopeObj)
: MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy),
StructuredCloneHolder(CloningSupported, TransferringNotSupported, StructuredCloneHolder(CloningSupported, TransferringNotSupported,
SameProcessDifferentThread), StructuredCloneScope::SameProcessDifferentThread),
mType(aType), mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0), mType(aType), mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0),
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0), mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0),

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

@ -22,6 +22,13 @@ struct JSStructuredCloneWriter;
// API for the HTML5 internal structured cloning algorithm. // API for the HTML5 internal structured cloning algorithm.
namespace JS { namespace JS {
enum class StructuredCloneScope : uint32_t {
SameProcessSameThread,
SameProcessDifferentThread,
DifferentProcess
};
enum TransferableOwnership { enum TransferableOwnership {
/** Transferable data has not been filled in yet */ /** Transferable data has not been filled in yet */
SCTAG_TMO_UNFILLED = 0, 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. // Increment this when anything at all changes in the serialization format.
// (Note that this does not need to be bumped for Transferable-only changes, // (Note that this does not need to be bumped for Transferable-only changes,
// since they are never saved to persistent storage.) // since they are never saved to persistent storage.)
#define JS_STRUCTURED_CLONE_VERSION 6 #define JS_STRUCTURED_CLONE_VERSION 7
struct JSStructuredCloneCallbacks { struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read; ReadStructuredCloneOp read;
@ -148,6 +155,7 @@ struct JSStructuredCloneCallbacks {
/** Note: if the *data contains transferable objects, it can be read only once. */ /** Note: if the *data contains transferable objects, it can be read only once. */
JS_PUBLIC_API(bool) JS_PUBLIC_API(bool)
JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t version, JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t version,
JS::StructuredCloneScope scope,
JS::MutableHandleValue vp, JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure); 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_PUBLIC_API(bool)
JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp, JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp,
JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* optionalCallbacks, const JSStructuredCloneCallbacks* optionalCallbacks,
void* closure, JS::HandleValue transferable); void* closure, JS::HandleValue transferable);
@ -174,6 +183,7 @@ JS_StructuredClone(JSContext* cx, JS::HandleValue v, JS::MutableHandleValue vp,
/** RAII sugar for JS_WriteStructuredClone. */ /** RAII sugar for JS_WriteStructuredClone. */
class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) { class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
const JS::StructuredCloneScope scope_;
uint64_t* data_; uint64_t* data_;
size_t nbytes_; size_t nbytes_;
uint32_t version_; uint32_t version_;
@ -187,14 +197,9 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
void* closure_; void* closure_;
public: public:
JSAutoStructuredCloneBuffer() JSAutoStructuredCloneBuffer(JS::StructuredCloneScope scope,
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION), const JSStructuredCloneCallbacks* callbacks, void* closure)
ownTransferables_(NoTransferables), : scope_(scope), data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
callbacks_(nullptr), closure_(nullptr)
{}
JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks* callbacks, void* closure)
: data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
ownTransferables_(NoTransferables), ownTransferables_(NoTransferables),
callbacks_(callbacks), closure_(closure) callbacks_(callbacks), closure_(closure)
{} {}

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

@ -2212,7 +2212,7 @@ Serialize(JSContext* cx, unsigned argc, Value* vp)
{ {
CallArgs args = CallArgsFromVp(argc, 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))) if (!clonebuf.write(cx, args.get(0), args.get(1)))
return false; return false;
@ -2254,7 +2254,10 @@ Deserialize(JSContext* cx, unsigned argc, Value* vp)
RootedValue deserialized(cx); RootedValue deserialized(cx);
if (!JS_ReadStructuredClone(cx, obj->data(), obj->nbytes(), 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; return false;
} }
args.rval().set(deserialized); args.rval().set(deserialized);

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

@ -126,7 +126,7 @@ bool TestCloneObject()
{ {
JS::RootedObject obj1(cx, CreateNewObject(8, 12)); JS::RootedObject obj1(cx, CreateNewObject(8, 12));
CHECK(obj1); CHECK(obj1);
JSAutoStructuredCloneBuffer cloned_buffer; JSAutoStructuredCloneBuffer cloned_buffer(JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
JS::RootedValue v1(cx, JS::ObjectValue(*obj1)); JS::RootedValue v1(cx, JS::ObjectValue(*obj1));
CHECK(cloned_buffer.write(cx, v1, nullptr, nullptr)); CHECK(cloned_buffer.write(cx, v1, nullptr, nullptr));
JS::RootedValue v2(cx); JS::RootedValue v2(cx);
@ -164,7 +164,7 @@ bool TestTransferObject()
CHECK(obj); CHECK(obj);
JS::RootedValue transferable(cx, JS::ObjectValue(*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)); CHECK(cloned_buffer.write(cx, v1, transferable, nullptr, nullptr));
JS::RootedValue v2(cx); JS::RootedValue v2(cx);
CHECK(cloned_buffer.read(cx, &v2, nullptr, nullptr)); CHECK(cloned_buffer.read(cx, &v2, nullptr, nullptr));

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

@ -71,6 +71,7 @@ using JS::CanonicalizeNaN;
enum StructuredDataType : uint32_t { enum StructuredDataType : uint32_t {
/* Structured data types provided by the engine */ /* Structured data types provided by the engine */
SCTAG_FLOAT_MAX = 0xFFF00000, SCTAG_FLOAT_MAX = 0xFFF00000,
SCTAG_HEADER = 0xFFF10000,
SCTAG_NULL = 0xFFFF0000, SCTAG_NULL = 0xFFFF0000,
SCTAG_UNDEFINED, SCTAG_UNDEFINED,
SCTAG_BOOLEAN, SCTAG_BOOLEAN,
@ -226,9 +227,10 @@ class SCInput {
struct JSStructuredCloneReader { struct JSStructuredCloneReader {
public: public:
explicit JSStructuredCloneReader(SCInput& in, const JSStructuredCloneCallbacks* cb, explicit JSStructuredCloneReader(SCInput& in, JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* cb,
void* cbClosure) void* cbClosure)
: in(in), objs(in.context()), allObjs(in.context()), : in(in), scope(scope), objs(in.context()), allObjs(in.context()),
callbacks(cb), closure(cbClosure) { } callbacks(cb), closure(cbClosure) { }
SCInput& input() { return in; } SCInput& input() { return in; }
@ -237,6 +239,7 @@ struct JSStructuredCloneReader {
private: private:
JSContext* context() { return in.context(); } JSContext* context() { return in.context(); }
bool readHeader();
bool readTransferMap(); bool readTransferMap();
template <typename CharT> template <typename CharT>
@ -254,6 +257,8 @@ struct JSStructuredCloneReader {
SCInput& in; SCInput& in;
JS::StructuredCloneScope scope;
// Stack of objects with properties remaining to be read. // Stack of objects with properties remaining to be read.
AutoValueVector objs; AutoValueVector objs;
@ -272,10 +277,11 @@ struct JSStructuredCloneReader {
struct JSStructuredCloneWriter { struct JSStructuredCloneWriter {
public: public:
explicit JSStructuredCloneWriter(JSContext* cx, explicit JSStructuredCloneWriter(JSContext* cx,
JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* cb, const JSStructuredCloneCallbacks* cb,
void* cbClosure, void* cbClosure,
Value tVal) Value tVal)
: out(cx), objs(out.context()), : out(cx), scope(scope), objs(out.context()),
counts(out.context()), entries(out.context()), counts(out.context()), entries(out.context()),
memory(out.context()), callbacks(cb), memory(out.context()), callbacks(cb),
closure(cbClosure), transferable(out.context(), tVal), closure(cbClosure), transferable(out.context(), tVal),
@ -289,7 +295,7 @@ struct JSStructuredCloneWriter {
ReportOutOfMemory(context()); ReportOutOfMemory(context());
return false; return false;
} }
return parseTransferable() && writeTransferMap(); return parseTransferable() && writeHeader() && writeTransferMap();
} }
bool write(HandleValue v); bool write(HandleValue v);
@ -306,6 +312,7 @@ struct JSStructuredCloneWriter {
JSContext* context() { return out.context(); } JSContext* context() { return out.context(); }
bool writeHeader();
bool writeTransferMap(); bool writeTransferMap();
bool writeString(uint32_t tag, JSString* str); bool writeString(uint32_t tag, JSString* str);
@ -329,6 +336,9 @@ struct JSStructuredCloneWriter {
SCOutput out; 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. // Vector of objects with properties remaining to be written.
// //
// NB: These can span multiple compartments, so the compartment must be // NB: These can span multiple compartments, so the compartment must be
@ -411,19 +421,21 @@ ReportDataCloneError(JSContext* cx,
bool bool
WriteStructuredClone(JSContext* cx, HandleValue v, uint64_t** bufp, size_t* nbytesp, WriteStructuredClone(JSContext* cx, HandleValue v, uint64_t** bufp, size_t* nbytesp,
JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* cb, void* cbClosure, const JSStructuredCloneCallbacks* cb, void* cbClosure,
Value transferable) 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); return w.init() && w.write(v) && w.extractBuffer(bufp, nbytesp);
} }
bool 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) const JSStructuredCloneCallbacks* cb, void* cbClosure)
{ {
SCInput in(cx, data, nbytes); SCInput in(cx, data, nbytes);
JSStructuredCloneReader r(in, cb, cbClosure); JSStructuredCloneReader r(in, scope, cb, cbClosure);
return r.read(vp); return r.read(vp);
} }
@ -1263,6 +1275,12 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE); return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE);
} }
bool
JSStructuredCloneWriter::writeHeader()
{
return out.writePair(SCTAG_HEADER, (uint32_t)scope);
}
bool bool
JSStructuredCloneWriter::writeTransferMap() JSStructuredCloneWriter::writeTransferMap()
{ {
@ -1307,6 +1325,8 @@ JSStructuredCloneWriter::transferOwnership()
// grabbing out pointers from the transferables and stuffing them into the // grabbing out pointers from the transferables and stuffing them into the
// transfer map. // transfer map.
uint64_t* point = out.rawBuffer(); 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); MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_HEADER);
point++; point++;
MOZ_ASSERT(LittleEndian::readUint64(point) == transferableObjects.count()); MOZ_ASSERT(LittleEndian::readUint64(point) == transferableObjects.count());
@ -1342,6 +1362,8 @@ JSStructuredCloneWriter::transferOwnership()
// and malloc'd buffers, not asm.js-ified buffers. // and malloc'd buffers, not asm.js-ified buffers.
bool hasStealableContents = arrayBuffer->hasStealableContents() && bool hasStealableContents = arrayBuffer->hasStealableContents() &&
(arrayBuffer->isMapped() || arrayBuffer->hasMallocedContents()); (arrayBuffer->isMapped() || arrayBuffer->hasMallocedContents());
if (scope == JS::StructuredCloneScope::DifferentProcess)
hasStealableContents = false;
ArrayBufferObject::BufferContents bufContents = ArrayBufferObject::BufferContents bufContents =
ArrayBufferObject::stealContents(context(), arrayBuffer, hasStealableContents); ArrayBufferObject::stealContents(context(), arrayBuffer, hasStealableContents);
@ -1896,6 +1918,29 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
return true; 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 bool
JSStructuredCloneReader::readTransferMap() JSStructuredCloneReader::readTransferMap()
{ {
@ -2071,6 +2116,9 @@ JSStructuredCloneReader::readSavedFrame(uint32_t principalsTag)
bool bool
JSStructuredCloneReader::read(MutableHandleValue vp) JSStructuredCloneReader::read(MutableHandleValue vp)
{ {
if (!readHeader())
return false;
if (!readTransferMap()) if (!readTransferMap())
return false; return false;
@ -2178,7 +2226,8 @@ using namespace js;
JS_PUBLIC_API(bool) JS_PUBLIC_API(bool)
JS_ReadStructuredClone(JSContext* cx, uint64_t* buf, size_t nbytes, 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, const JSStructuredCloneCallbacks* optionalCallbacks,
void* closure) void* closure)
{ {
@ -2190,11 +2239,12 @@ JS_ReadStructuredClone(JSContext* cx, uint64_t* buf, size_t nbytes,
return false; return false;
} }
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks; 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_PUBLIC_API(bool)
JS_WriteStructuredClone(JSContext* cx, HandleValue value, uint64_t** bufp, size_t* nbytesp, JS_WriteStructuredClone(JSContext* cx, HandleValue value, uint64_t** bufp, size_t* nbytesp,
JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* optionalCallbacks, const JSStructuredCloneCallbacks* optionalCallbacks,
void* closure, HandleValue transferable) void* closure, HandleValue transferable)
{ {
@ -2203,7 +2253,7 @@ JS_WriteStructuredClone(JSContext* cx, HandleValue value, uint64_t** bufp, size_
assertSameCompartment(cx, value); assertSameCompartment(cx, value);
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks; 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) JS_PUBLIC_API(bool)
@ -2247,7 +2297,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks; 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 // If we use Maybe<AutoCompartment> here, G++ can't tell that the
// destructor is only called when Maybe::construct was called, and // 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) JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
: scope_(other.scope_)
{ {
ownTransferables_ = other.ownTransferables_; ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_); other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
@ -2275,6 +2326,7 @@ JSAutoStructuredCloneBuffer&
JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other) JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
{ {
MOZ_ASSERT(&other != this); MOZ_ASSERT(&other != this);
MOZ_ASSERT(scope_ == other.scope_);
clear(); clear();
ownTransferables_ = other.ownTransferables_; ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_); other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
@ -2369,7 +2421,7 @@ JSAutoStructuredCloneBuffer::read(JSContext* cx, MutableHandleValue vp,
{ {
MOZ_ASSERT(cx); MOZ_ASSERT(cx);
MOZ_ASSERT(data_); MOZ_ASSERT(data_);
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp, return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, scope_, vp,
optionalCallbacks, closure); optionalCallbacks, closure);
} }
@ -2390,6 +2442,7 @@ JSAutoStructuredCloneBuffer::write(JSContext* cx, HandleValue value,
{ {
clear(); clear();
bool ok = JS_WriteStructuredClone(cx, value, &data_, &nbytes_, bool ok = JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
scope_,
optionalCallbacks, closure, optionalCallbacks, closure,
transferable); transferable);