зеркало из 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,
|
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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче