Bug 1176034 - Implement JSAutoStructuredCloneBuffer::clear(with callbacks and closure), r=sfink
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 06 Jul 2015 12:22:08 +0100
changeset 275864 2df2e0c0a7b4dc6acb8f4d604fb82840119cbbf9
parent 275863 9dbcee65bcee2c7c1726cb454eab49881f5b5de3
child 275865 146b55675c93adf46164f124b2fb8012ab44e2a1
push id3246
push usergijskruitbosch@gmail.com
push dateTue, 07 Jul 2015 09:06:38 +0000
reviewerssfink
bugs1176034
milestone42.0a1
Bug 1176034 - Implement JSAutoStructuredCloneBuffer::clear(with callbacks and closure), r=sfink
dom/workers/WorkerPrivate.cpp
js/public/StructuredClone.h
js/src/vm/StructuredClone.cpp
--- 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;