Bug 1176034 - Implement JSAutoStructuredCloneBuffer::clear(with callbacks and closure), r=sfink
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3539,22 +3539,48 @@ bool
WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
JSContext* aCx, uint64_t aMessagePortSerial,
JSAutoStructuredCloneBuffer&& aBuffer,
WorkerStructuredCloneClosure& aClosure)
{
AssertIsOnMainThread();
JSAutoStructuredCloneBuffer buffer(Move(aBuffer));
+ const JSStructuredCloneCallbacks* callbacks =
+ WorkerStructuredCloneCallbacks(true);
+
+ class MOZ_STACK_CLASS AutoCloneBufferCleaner final
+ {
+ public:
+ AutoCloneBufferCleaner(JSAutoStructuredCloneBuffer& aBuffer,
+ const JSStructuredCloneCallbacks* aCallbacks,
+ WorkerStructuredCloneClosure& aClosure)
+ : mBuffer(aBuffer)
+ , mCallbacks(aCallbacks)
+ , mClosure(aClosure)
+ {}
+
+ ~AutoCloneBufferCleaner()
+ {
+ mBuffer.clear(mCallbacks, &mClosure);
+ }
+
+ private:
+ JSAutoStructuredCloneBuffer& mBuffer;
+ const JSStructuredCloneCallbacks* mCallbacks;
+ WorkerStructuredCloneClosure& mClosure;
+ };
WorkerStructuredCloneClosure closure;
closure.mClonedObjects.SwapElements(aClosure.mClonedObjects);
MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
closure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers);
+ AutoCloneBufferCleaner bufferCleaner(buffer, callbacks, closure);
+
SharedWorker* sharedWorker;
if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) {
// SharedWorker has already been unregistered?
return true;
}
nsRefPtr<MessagePort> port = sharedWorker->Port();
NS_ASSERTION(port, "SharedWorkers always have a port!");
@@ -3572,18 +3598,16 @@ WorkerPrivateParent<Derived>::DispatchMe
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> data(cx);
if (!buffer.read(cx, &data, WorkerStructuredCloneCallbacks(true),
&closure)) {
return false;
}
- buffer.clear();
-
nsRefPtr<MessageEvent> event = new MessageEvent(port, nullptr, nullptr);
nsresult rv =
event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data,
EmptyString(), EmptyString(), nullptr);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return false;
}
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -187,17 +187,17 @@ class JS_PUBLIC_API(JSAutoStructuredClon
JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other);
JSAutoStructuredCloneBuffer& operator=(JSAutoStructuredCloneBuffer&& other);
~JSAutoStructuredCloneBuffer() { clear(); }
uint64_t* data() const { return data_; }
size_t nbytes() const { return nbytes_; }
- void clear();
+ void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
// Copy some memory. It will be automatically freed by the destructor.
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
// Adopt some memory. It will be automatically freed by the destructor.
// data must have been allocated by the JS engine (e.g., extracted via
// JSAutoStructuredCloneBuffer::steal).
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1979,27 +1979,33 @@ JSAutoStructuredCloneBuffer::operator=(J
MOZ_ASSERT(&other != this);
clear();
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_);
return *this;
}
void
-JSAutoStructuredCloneBuffer::clear()
+JSAutoStructuredCloneBuffer::clear(const JSStructuredCloneCallbacks* optionalCallbacks,
+ void* optionalClosure)
{
- if (data_) {
- if (ownTransferables_ == OwnsTransferablesIfAny)
- DiscardTransferables(data_, nbytes_, callbacks_, closure_);
- ownTransferables_ = NoTransferables;
- js_free(data_);
- data_ = nullptr;
- nbytes_ = 0;
- version_ = 0;
- }
+ if (!data_)
+ return;
+
+ const JSStructuredCloneCallbacks* callbacks =
+ optionalCallbacks ? optionalCallbacks : callbacks_;
+ void* closure = optionalClosure ? optionalClosure : closure_;
+
+ if (ownTransferables_ == OwnsTransferablesIfAny)
+ DiscardTransferables(data_, nbytes_, callbacks, closure);
+ ownTransferables_ = NoTransferables;
+ js_free(data_);
+ data_ = nullptr;
+ nbytes_ = 0;
+ version_ = 0;
}
bool
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
{
// transferable objects cannot be copied
if (StructuredCloneHasTransferObjects(data_, nbytes_))
return false;