Backed out changeset f6d29009ae0a (bug 1184557) for crashes in fetch-csp.https.html web platform tests CLOSED TREE

This commit is contained in:
Wes Kocher 2015-07-22 13:57:09 -07:00
parent 3f571178bb
commit 5419f7038e
5 changed files with 333 additions and 343 deletions

View File

@ -23,6 +23,246 @@
namespace mozilla {
namespace dom {
namespace {
struct StructuredCloneInfo
{
PostMessageEvent* event;
nsPIDOMWindow* window;
// This hashtable contains the transferred ports - used to avoid duplicates.
nsTArray<nsRefPtr<MessagePortBase>> transferredPorts;
// This array is populated when the ports are cloned.
nsTArray<nsRefPtr<MessagePortBase>> clonedPorts;
};
} // namespace
const JSStructuredCloneCallbacks PostMessageEvent::sPostMessageCallbacks = {
PostMessageEvent::ReadStructuredClone,
PostMessageEvent::WriteStructuredClone,
nullptr,
PostMessageEvent::ReadTransferStructuredClone,
PostMessageEvent::TransferStructuredClone,
PostMessageEvent::FreeTransferStructuredClone
};
/* static */ JSObject*
PostMessageEvent::ReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
uint32_t tag,
uint32_t data,
void* closure)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
NS_ASSERTION(scInfo, "Must have scInfo!");
if (tag == SCTAG_DOM_BLOB) {
NS_ASSERTION(!data, "Data should be empty");
// What we get back from the reader is a BlobImpl.
// From that we create a new File.
BlobImpl* blobImpl;
if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
MOZ_ASSERT(blobImpl);
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
// while destructors are running.
JS::Rooted<JS::Value> val(cx);
{
nsRefPtr<Blob> blob = Blob::Create(scInfo->window, blobImpl);
if (!ToJSValue(cx, blob, &val)) {
return nullptr;
}
}
return &val.toObject();
}
}
if (tag == SCTAG_DOM_FILELIST) {
NS_ASSERTION(!data, "Data should be empty");
// What we get back from the reader is a FileListClonedData.
// From that we create a new FileList.
FileListClonedData* fileListClonedData;
if (JS_ReadBytes(reader, &fileListClonedData, sizeof(fileListClonedData))) {
MOZ_ASSERT(fileListClonedData);
// nsRefPtr<FileList> needs to go out of scope before toObjectOrNull() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
// while destructors are running.
JS::Rooted<JS::Value> val(cx);
{
nsRefPtr<FileList> fileList =
FileList::Create(scInfo->window, fileListClonedData);
if (!fileList || !ToJSValue(cx, fileList, &val)) {
return nullptr;
}
}
return &val.toObject();
}
}
const JSStructuredCloneCallbacks* runtimeCallbacks =
js::GetContextStructuredCloneCallbacks(cx);
if (runtimeCallbacks) {
return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
}
return nullptr;
}
/* static */ bool
PostMessageEvent::WriteStructuredClone(JSContext* cx,
JSStructuredCloneWriter* writer,
JS::Handle<JSObject*> obj,
void *closure)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
NS_ASSERTION(scInfo, "Must have scInfo!");
// See if this is a File/Blob object.
{
Blob* blob = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
BlobImpl* blobImpl = blob->Impl();
if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
scInfo->event->StoreISupports(blobImpl);
return true;
}
}
}
// See if this is a FileList object.
{
FileList* fileList = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, obj, fileList))) {
nsRefPtr<FileListClonedData> fileListClonedData =
fileList->CreateClonedData();
MOZ_ASSERT(fileListClonedData);
FileListClonedData* ptr = fileListClonedData.get();
if (JS_WriteUint32Pair(writer, SCTAG_DOM_FILELIST, 0) &&
JS_WriteBytes(writer, &ptr, sizeof(ptr))) {
scInfo->event->StoreISupports(fileListClonedData);
return true;
}
}
}
const JSStructuredCloneCallbacks* runtimeCallbacks =
js::GetContextStructuredCloneCallbacks(cx);
if (runtimeCallbacks) {
return runtimeCallbacks->write(cx, writer, obj, nullptr);
}
return false;
}
/* static */ bool
PostMessageEvent::ReadTransferStructuredClone(JSContext* aCx,
JSStructuredCloneReader* reader,
uint32_t tag, void* aData,
uint64_t aExtraData,
void* aClosure,
JS::MutableHandle<JSObject*> returnObject)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
NS_ASSERTION(scInfo, "Must have scInfo!");
if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
MOZ_ASSERT(!aData);
// aExtraData is the index of this port identifier.
ErrorResult rv;
nsRefPtr<MessagePort> port =
MessagePort::Create(scInfo->window,
scInfo->event->GetPortIdentifier(aExtraData),
rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}
scInfo->clonedPorts.AppendElement(port);
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, port, &value)) {
JS_ClearPendingException(aCx);
return false;
}
returnObject.set(&value.toObject());
return true;
}
return false;
}
/* static */ bool
PostMessageEvent::TransferStructuredClone(JSContext* aCx,
JS::Handle<JSObject*> aObj,
void* aClosure,
uint32_t* aTag,
JS::TransferableOwnership* aOwnership,
void** aContent,
uint64_t* aExtraData)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
NS_ASSERTION(scInfo, "Must have scInfo!");
MessagePortBase* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
if (NS_SUCCEEDED(rv)) {
if (scInfo->transferredPorts.Contains(port)) {
// No duplicates.
return false;
}
// We use aExtraData to store the index of this new port identifier.
MessagePortIdentifier* identifier =
scInfo->event->NewPortIdentifier(aExtraData);
if (!port->CloneAndDisentangle(*identifier)) {
return false;
}
scInfo->transferredPorts.AppendElement(port);
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
*aOwnership = JS::SCTAG_TMO_CUSTOM;
*aContent = nullptr;
return true;
}
return false;
}
/* static */ void
PostMessageEvent::FreeTransferStructuredClone(uint32_t aTag,
JS::TransferableOwnership aOwnership,
void *aContent,
uint64_t aExtraData,
void* aClosure)
{
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
MOZ_ASSERT(aClosure);
MOZ_ASSERT(!aContent);
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
MessagePort::ForceClose(scInfo->event->GetPortIdentifier(aExtraData));
}
}
PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
const nsAString& aCallerOrigin,
nsGlobalWindow* aTargetWindow,
@ -42,6 +282,20 @@ PostMessageEvent::~PostMessageEvent()
MOZ_COUNT_DTOR(PostMessageEvent);
}
const MessagePortIdentifier&
PostMessageEvent::GetPortIdentifier(uint64_t aId)
{
MOZ_ASSERT(aId < mPortIdentifiers.Length());
return mPortIdentifiers[aId];
}
MessagePortIdentifier*
PostMessageEvent::NewPortIdentifier(uint64_t* aPosition)
{
*aPosition = mPortIdentifiers.Length();
return mPortIdentifiers.AppendElement();
}
NS_IMETHODIMP
PostMessageEvent::Run()
{
@ -93,9 +347,13 @@ PostMessageEvent::Run()
}
}
// Deserialize the structured clone data
JS::Rooted<JS::Value> messageData(cx);
nsCOMPtr<nsPIDOMWindow> window = targetWindow.get();
if (!Read(window, cx, &messageData)) {
StructuredCloneInfo scInfo;
scInfo.event = this;
scInfo.window = targetWindow;
if (!mBuffer.read(cx, &messageData, &sPostMessageCallbacks, &scInfo)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -110,7 +368,7 @@ PostMessageEvent::Run()
EmptyString(), mSource);
event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
GetTransferredPorts()));
scInfo.clonedPorts));
// We can't simply call dispatchEvent on the window because doing so ends
// up flipping the trusted bit on the event, and we don't want that to
@ -134,5 +392,19 @@ PostMessageEvent::Run()
return NS_OK;
}
bool
PostMessageEvent::Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
JS::Handle<JS::Value> aTransfer, nsPIDOMWindow* aWindow)
{
// We *must* clone the data here, or the JS::Value could be modified
// by script
StructuredCloneInfo scInfo;
scInfo.event = this;
scInfo.window = aWindow;
return mBuffer.write(aCx, aMessage, aTransfer, &sPostMessageCallbacks,
&scInfo);
}
} // namespace dom
} // namespace mozilla

View File

@ -7,7 +7,7 @@
#ifndef mozilla_dom_PostMessageEvent_h
#define mozilla_dom_PostMessageEvent_h
#include "mozilla/dom/StructuredCloneHelper.h"
#include "js/StructuredClone.h"
#include "nsCOMPtr.h"
#include "nsRefPtr.h"
#include "nsTArray.h"
@ -28,7 +28,6 @@ class MessagePortIdentifier;
* which asynchronously creates and dispatches events.
*/
class PostMessageEvent final : public nsRunnable
, public StructuredCloneHelper
{
public:
NS_DECL_NSIRUNNABLE
@ -39,14 +38,69 @@ public:
nsIPrincipal* aProvidedPrincipal,
bool aTrustedCaller);
bool Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
JS::Handle<JS::Value> aTransfer, nsPIDOMWindow* aWindow);
private:
~PostMessageEvent();
const MessagePortIdentifier& GetPortIdentifier(uint64_t aId);
MessagePortIdentifier* NewPortIdentifier(uint64_t* aPosition);
bool StoreISupports(nsISupports* aSupports)
{
mSupportsArray.AppendElement(aSupports);
return true;
}
static JSObject*
ReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
uint32_t tag,
uint32_t data,
void* closure);
static bool
WriteStructuredClone(JSContext* cx,
JSStructuredCloneWriter* writer,
JS::Handle<JSObject*> obj,
void *closure);
static bool
ReadTransferStructuredClone(JSContext* aCx,
JSStructuredCloneReader* reader,
uint32_t tag, void* aData,
uint64_t aExtraData,
void* aClosure,
JS::MutableHandle<JSObject*> returnObject);
static bool
TransferStructuredClone(JSContext* aCx,
JS::Handle<JSObject*> aObj,
void* aClosure,
uint32_t* aTag,
JS::TransferableOwnership* aOwnership,
void** aContent,
uint64_t* aExtraData);
static void
FreeTransferStructuredClone(uint32_t aTag,
JS::TransferableOwnership aOwnership,
void *aContent,
uint64_t aExtraData,
void* aClosure);
static const JSStructuredCloneCallbacks sPostMessageCallbacks;
JSAutoStructuredCloneBuffer mBuffer;
nsRefPtr<nsGlobalWindow> mSource;
nsString mCallerOrigin;
nsRefPtr<nsGlobalWindow> mTargetWindow;
nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
bool mTrustedCaller;
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
nsTArray<MessagePortIdentifier> mPortIdentifiers;
};
} // namespace dom

View File

@ -6,10 +6,6 @@
#include "StructuredCloneHelper.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/FileListBinding.h"
#include "mozilla/dom/StructuredCloneTags.h"
namespace mozilla {
namespace dom {
@ -103,8 +99,6 @@ const JSStructuredCloneCallbacks gCallbacks = {
} // anonymous namespace
// StructuredCloneHelperInternal class
bool
StructuredCloneHelperInternal::Write(JSContext* aCx,
JS::Handle<JS::Value> aValue)
@ -115,17 +109,6 @@ StructuredCloneHelperInternal::Write(JSContext* aCx,
return mBuffer->write(aCx, aValue, &gCallbacks, this);
}
bool
StructuredCloneHelperInternal::Write(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aTransfer)
{
MOZ_ASSERT(!mBuffer, "Double Write is not allowed");
mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this);
return mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this);
}
bool
StructuredCloneHelperInternal::Read(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue)
@ -149,6 +132,7 @@ StructuredCloneHelperInternal::ReadTransferCallback(JSContext* aCx,
return false;
}
bool
StructuredCloneHelperInternal::WriteTransferCallback(JSContext* aCx,
JS::Handle<JSObject*> aObj,
@ -170,220 +154,5 @@ StructuredCloneHelperInternal::FreeTransferCallback(uint32_t aTag,
MOZ_CRASH("Nothing to free.");
}
// StructuredCloneHelper class
StructuredCloneHelper::StructuredCloneHelper(uint32_t aFlags)
: mFlags(aFlags)
, mParent(nullptr)
{}
StructuredCloneHelper::~StructuredCloneHelper()
{}
bool
StructuredCloneHelper::Write(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aTransfer)
{
bool ok = StructuredCloneHelperInternal::Write(aCx, aValue, aTransfer);
mTransferringPort.Clear();
return ok;
}
bool
StructuredCloneHelper::Read(nsISupports* aParent,
JSContext* aCx,
JS::MutableHandle<JS::Value> aValue)
{
mozilla::AutoRestore<nsISupports*> guard(mParent);
mParent = aParent;
return StructuredCloneHelperInternal::Read(aCx, aValue);
}
JSObject*
StructuredCloneHelper::ReadCallback(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
uint32_t aIndex)
{
if (aTag == SCTAG_DOM_BLOB) {
MOZ_ASSERT(!(mFlags & eBlobNotSupported));
BlobImpl* blobImpl;
if (JS_ReadBytes(aReader, &blobImpl, sizeof(blobImpl))) {
MOZ_ASSERT(blobImpl);
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
// while destructors are running.
JS::Rooted<JS::Value> val(aCx);
{
nsRefPtr<Blob> blob = Blob::Create(mParent, blobImpl);
if (!ToJSValue(aCx, blob, &val)) {
return nullptr;
}
}
return &val.toObject();
}
}
if (aTag == SCTAG_DOM_FILELIST) {
MOZ_ASSERT(!(mFlags & eFileListNotSupported));
FileListClonedData* fileListClonedData;
if (JS_ReadBytes(aReader, &fileListClonedData,
sizeof(fileListClonedData))) {
MOZ_ASSERT(fileListClonedData);
// nsRefPtr<FileList> needs to go out of scope before toObjectOrNull() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
// while destructors are running.
JS::Rooted<JS::Value> val(aCx);
{
nsRefPtr<FileList> fileList =
FileList::Create(mParent, fileListClonedData);
if (!fileList || !ToJSValue(aCx, fileList, &val)) {
return nullptr;
}
}
return &val.toObject();
}
}
return NS_DOMReadStructuredClone(aCx, aReader, aTag, aIndex, nullptr);
}
bool
StructuredCloneHelper::WriteCallback(JSContext* aCx,
JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj)
{
// See if this is a File/Blob object.
if (!(mFlags & eBlobNotSupported)) {
Blob* blob = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
BlobImpl* blobImpl = blob->Impl();
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, 0) &&
JS_WriteBytes(aWriter, &blobImpl, sizeof(blobImpl)) &&
StoreISupports(blobImpl);
}
}
if (!(mFlags & eFileListNotSupported)) {
FileList* fileList = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) {
nsRefPtr<FileListClonedData> fileListClonedData =
fileList->CreateClonedData();
MOZ_ASSERT(fileListClonedData);
FileListClonedData* ptr = fileListClonedData.get();
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST, 0) &&
JS_WriteBytes(aWriter, &ptr, sizeof(ptr)) &&
StoreISupports(fileListClonedData);
}
}
return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
}
bool
StructuredCloneHelper::ReadTransferCallback(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
void* aContent,
uint64_t aExtraData,
JS::MutableHandleObject aReturnObject)
{
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
// This can be null.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mParent);
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
const MessagePortIdentifier& portIdentifier = mPortIdentifiers[aExtraData];
// aExtraData is the index of this port identifier.
ErrorResult rv;
nsRefPtr<MessagePort> port =
MessagePort::Create(window, portIdentifier, rv);
if (NS_WARN_IF(rv.Failed())) {
return false;
}
mTransferredPorts.AppendElement(port);
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, port, &value)) {
JS_ClearPendingException(aCx);
return false;
}
aReturnObject.set(&value.toObject());
return true;
}
return false;
}
bool
StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
JS::Handle<JSObject*> aObj,
uint32_t* aTag,
JS::TransferableOwnership* aOwnership,
void** aContent,
uint64_t* aExtraData)
{
if (!(mFlags & eMessagePortNotSupported)) {
MessagePortBase* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
if (NS_SUCCEEDED(rv)) {
if (mTransferringPort.Contains(port)) {
// No duplicates.
return false;
}
// We use aExtraData to store the index of this new port identifier.
*aExtraData = mPortIdentifiers.Length();
MessagePortIdentifier* identifier = mPortIdentifiers.AppendElement();
if (!port->CloneAndDisentangle(*identifier)) {
return false;
}
mTransferringPort.AppendElement(port);
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
*aOwnership = JS::SCTAG_TMO_CUSTOM;
*aContent = nullptr;
return true;
}
}
return false;
}
void
StructuredCloneHelper::FreeTransferCallback(uint32_t aTag,
JS::TransferableOwnership aOwnership,
void* aContent,
uint64_t aExtraData)
{
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
MOZ_ASSERT(!aContent);
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
}
}
} // dom namespace
} // mozilla namespace

View File

@ -8,8 +8,6 @@
#include "js/StructuredClone.h"
#include "nsAutoPtr.h"
#include "nsISupports.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
@ -71,109 +69,6 @@ protected:
nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer;
};
class MessagePortBase;
class MessagePortIdentifier;
class StructuredCloneHelper : public StructuredCloneHelperInternal
{
public:
enum StructuredCloneHelperFlags {
eAll = 0,
// Disable the cloning of blobs. If a blob is part of the cloning value,
// an exception will be thrown.
eBlobNotSupported = 1 << 0,
// Disable the cloning of FileLists. If a FileList is part of the cloning
// value, an exception will be thrown.
eFileListNotSupported = 1 << 1,
// MessagePort can just be transfered. Using this flag we do not support
// the transfering.
eMessagePortNotSupported = 1 << 2,
};
// aFlags is a bitmap of StructuredCloneHelperFlags.
explicit StructuredCloneHelper(uint32_t aFlags = eAll);
virtual ~StructuredCloneHelper();
bool Write(JSContext* aCx,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aTransfer);
bool Read(nsISupports* aParent,
JSContext* aCx,
JS::MutableHandle<JS::Value> aValue);
nsTArray<nsRefPtr<MessagePortBase>>& GetTransferredPorts()
{
MOZ_ASSERT(!(mFlags & eMessagePortNotSupported));
return mTransferredPorts;
}
// Custom Callbacks
virtual JSObject* ReadCallback(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
uint32_t aIndex) override;
virtual bool WriteCallback(JSContext* aCx,
JSStructuredCloneWriter* aWriter,
JS::Handle<JSObject*> aObj) override;
virtual bool ReadTransferCallback(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
void* aContent,
uint64_t aExtraData,
JS::MutableHandleObject aReturnObject) override;
virtual bool WriteTransferCallback(JSContext* aCx,
JS::Handle<JSObject*> aObj,
uint32_t* aTag,
JS::TransferableOwnership* aOwnership,
void** aContent,
uint64_t* aExtraData) override;
virtual void FreeTransferCallback(uint32_t aTag,
JS::TransferableOwnership aOwnership,
void* aContent,
uint64_t aExtraData) override;
private:
bool StoreISupports(nsISupports* aSupports)
{
MOZ_ASSERT(aSupports);
mSupportsArray.AppendElement(aSupports);
return true;
}
// This is our bitmap.
uint32_t mFlags;
// Useful for the structured clone algorithm:
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
// This raw pointer is set and unset into the ::Read(). It's always null
// outside that method. For this reason it's a raw pointer.
nsISupports* MOZ_NON_OWNING_REF mParent;
// This hashtable contains the ports while doing write (transferring and
// mapping transferred objects to the objects in the clone). It's an empty
// array outside the 'Write()' method.
nsTArray<nsRefPtr<MessagePortBase>> mTransferringPort;
// This array contains the ports once we've finished the reading. It's
// generated from the mPortIdentifiers array.
nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
// This array contains the identifiers of the MessagePorts. Based on these we
// are able to reconnect the new transferred ports with the other
// MessageChannel ports.
nsTArray<MessagePortIdentifier> mPortIdentifiers;
};
} // dom namespace
} // mozilla namespace

View File

@ -8564,7 +8564,7 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessa
JS::Rooted<JS::Value> message(aCx, aMessage);
JS::Rooted<JS::Value> transfer(aCx, aTransfer);
if (!event->Write(aCx, message, transfer)) {
if (!event->Write(aCx, message, transfer, this)) {
aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return;
}