Bug 1350254 part 2. Switch ImageData to [Serializable]. r=baku
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 25 Jun 2019 06:44:38 +0000
changeset 543280 0a7cdfb04b876e2df9b4bfd3932fe5c1b243ec7d
parent 543279 d27f30e55f4e421b8ab89b01a9dd9dcfdefec9c9
child 543281 f8b0c0b1aa91a9d6eca5cf45691664da92d23035
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1350254
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1350254 part 2. Switch ImageData to [Serializable]. r=baku Differential Revision: https://phabricator.services.mozilla.com/D35716
dom/base/StructuredCloneHolder.cpp
dom/bindings/StructuredClone.cpp
dom/bindings/StructuredClone.h
dom/bindings/moz.build
dom/canvas/ImageData.cpp
dom/canvas/ImageData.h
dom/webidl/ImageData.webidl
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "StructuredCloneHolder.h"
 
 #include "ImageContainer.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/CryptoKey.h"
 #include "mozilla/dom/StructuredCloneBlob.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DirectoryBinding.h"
 #include "mozilla/dom/DOMMatrix.h"
 #include "mozilla/dom/DOMMatrixBinding.h"
 #include "mozilla/dom/DOMPoint.h"
@@ -22,32 +23,30 @@
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/DOMRectBinding.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileList.h"
 #include "mozilla/dom/FileListBinding.h"
 #include "mozilla/dom/FormData.h"
 #include "mozilla/dom/ImageBitmap.h"
 #include "mozilla/dom/ImageBitmapBinding.h"
-#include "mozilla/dom/ImageData.h"
-#include "mozilla/dom/ImageDataBinding.h"
-#include "mozilla/dom/StructuredClone.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/OffscreenCanvas.h"
 #include "mozilla/dom/OffscreenCanvasBinding.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/StructuredCloneTester.h"
 #include "mozilla/dom/StructuredCloneTesterBinding.h"
 #include "mozilla/dom/SubtleCryptoBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "mozilla/dom/URLSearchParamsBinding.h"
 #include "mozilla/dom/WebCryptoCommon.h"
+#include "mozilla/dom/WebIDLSerializable.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "MultipartBlobImpl.h"
 #include "nsQueryObject.h"
 
 #ifdef MOZ_WEBRTC
@@ -344,30 +343,32 @@ void StructuredCloneHolder::ReadFromBuff
   }
 }
 
 /* static */
 JSObject* StructuredCloneHolder::ReadFullySerializableObjects(
     JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag) {
   AssertTagValues();
 
-  if (aTag == SCTAG_DOM_IMAGEDATA) {
-    return ReadStructuredCloneImageData(aCx, aReader);
+  nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
+  if (!global) {
+    return nullptr;
+  }
+
+  WebIDLDeserializer deserializer =
+      LookupDeserializer(StructuredCloneTags(aTag));
+  if (deserializer) {
+    return deserializer(aCx, global, aReader);
   }
 
   if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS ||
       aTag == SCTAG_DOM_DOMPOINT || aTag == SCTAG_DOM_DOMPOINT_READONLY ||
       aTag == SCTAG_DOM_DOMRECT || aTag == SCTAG_DOM_DOMRECT_READONLY ||
       aTag == SCTAG_DOM_DOMQUAD || aTag == SCTAG_DOM_DOMMATRIX ||
       aTag == SCTAG_DOM_DOMMATRIX_READONLY) {
-    nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
-    if (!global) {
-      return nullptr;
-    }
-
     // Prevent the return value from being trashed by a GC during ~nsRefPtr.
     JS::Rooted<JSObject*> result(aCx);
     {
       if (aTag == SCTAG_DOM_WEBCRYPTO_KEY) {
         RefPtr<CryptoKey> key = new CryptoKey(global);
         if (!key->ReadStructuredClone(aReader)) {
           result = nullptr;
         } else {
@@ -495,24 +496,26 @@ JSObject* StructuredCloneHolder::ReadFul
 }
 
 /* static */
 bool StructuredCloneHolder::WriteFullySerializableObjects(
     JSContext* aCx, JSStructuredCloneWriter* aWriter,
     JS::Handle<JSObject*> aObj) {
   AssertTagValues();
 
-  JS::Rooted<JSObject*> obj(aCx, aObj);
+  // Window and Location are not serializable, so it's OK to just do a static
+  // unwrap here.
+  JS::Rooted<JSObject*> obj(aCx, js::CheckedUnwrapStatic(aObj));
+  if (!obj) {
+    return xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
+  }
 
-  // See if this is a ImageData object.
-  {
-    ImageData* imageData = nullptr;
-    if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageData, &obj, imageData))) {
-      return WriteStructuredCloneImageData(aCx, aWriter, imageData);
-    }
+  const DOMJSClass* domClass = GetDOMClass(obj);
+  if (domClass && domClass->mSerializer) {
+    return domClass->mSerializer(aCx, aWriter, obj);
   }
 
   // Handle URLSearchParams cloning
   {
     URLSearchParams* usp = nullptr;
     if (NS_SUCCEEDED(UNWRAP_OBJECT(URLSearchParams, &obj, usp))) {
       return JS_WriteUint32Pair(aWriter, SCTAG_DOM_URLSEARCHPARAMS, 0) &&
              usp->WriteStructuredClone(aWriter);
deleted file mode 100644
--- a/dom/bindings/StructuredClone.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/StructuredClone.h"
-
-#include "js/StructuredClone.h"
-#include "mozilla/dom/ImageData.h"
-#include "mozilla/dom/StructuredCloneTags.h"
-
-namespace mozilla {
-namespace dom {
-
-JSObject* ReadStructuredCloneImageData(JSContext* aCx,
-                                       JSStructuredCloneReader* aReader) {
-  // Read the information out of the stream.
-  uint32_t width, height;
-  JS::Rooted<JS::Value> dataArray(aCx);
-  if (!JS_ReadUint32Pair(aReader, &width, &height) ||
-      !JS_ReadTypedArray(aReader, &dataArray)) {
-    return nullptr;
-  }
-  MOZ_ASSERT(dataArray.isObject());
-
-  // Protect the result from a moving GC in ~nsRefPtr.
-  JS::Rooted<JSObject*> result(aCx);
-  {
-    // Construct the ImageData.
-    RefPtr<ImageData> imageData =
-        new ImageData(width, height, dataArray.toObject());
-    // Wrap it in a JS::Value.
-    if (!imageData->WrapObject(aCx, nullptr, &result)) {
-      return nullptr;
-    }
-  }
-  return result;
-}
-
-bool WriteStructuredCloneImageData(JSContext* aCx,
-                                   JSStructuredCloneWriter* aWriter,
-                                   ImageData* aImageData) {
-  uint32_t width = aImageData->Width();
-  uint32_t height = aImageData->Height();
-
-  JS::Rooted<JSObject*> dataArray(aCx, aImageData->GetDataObject());
-  if (!JS_WrapObject(aCx, &dataArray)) {
-    return false;
-  }
-
-  JS::Rooted<JS::Value> arrayValue(aCx, JS::ObjectValue(*dataArray));
-  return JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEDATA, 0) &&
-         JS_WriteUint32Pair(aWriter, width, height) &&
-         JS_WriteTypedArray(aWriter, arrayValue);
-}
-
-}  // namespace dom
-}  // namespace mozilla
deleted file mode 100644
--- a/dom/bindings/StructuredClone.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-class JSObject;
-struct JSContext;
-struct JSStructuredCloneReader;
-struct JSStructuredCloneWriter;
-
-namespace mozilla {
-namespace dom {
-
-class ImageData;
-
-JSObject* ReadStructuredCloneImageData(JSContext* aCx,
-                                       JSStructuredCloneReader* aReader);
-
-bool WriteStructuredCloneImageData(JSContext* aCx,
-                                   JSStructuredCloneWriter* aWriter,
-                                   ImageData* aImageData);
-
-}  // namespace dom
-}  // namespace mozilla
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -45,17 +45,16 @@ EXPORTS.mozilla.dom += [
     'Nullable.h',
     'PrimitiveConversions.h',
     'ReadableStream.h',
     'Record.h',
     'RemoteObjectProxy.h',
     'RootedDictionary.h',
     'SimpleGlobalObject.h',
     'SpiderMonkeyInterface.h',
-    'StructuredClone.h',
     'ToJSValue.h',
     'TypedArray.h',
     'UnionMember.h',
     'WebIDLGlobalNameHash.h',
     'XrayExpandoClass.h',
 ]
 
 # Generated bindings reference *Binding.h, not mozilla/dom/*Binding.h. And,
@@ -111,20 +110,16 @@ UNIFIED_SOURCES += [
     'nsScriptError.cpp',
     'nsScriptErrorWithStack.cpp',
     'RemoteObjectProxy.cpp',
     'SimpleGlobalObject.cpp',
     'ToJSValue.cpp',
     'WebIDLGlobalNameHash.cpp',
 ]
 
-SOURCES += [
-    'StructuredClone.cpp',
-]
-
 # Some tests, including those for for maplike and setlike, require bindings
 # to be built, which means they must be included in libxul. This breaks the
 # "no test classes are exported" rule stated in the test/ directory, but it's
 # the only way this will work. Test classes are only built in debug mode, and
 # all tests requiring use of them are only run in debug mode.
 if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
     EXPORTS.mozilla.dom += [
         "test/TestFunctions.h",
--- a/dom/canvas/ImageData.cpp
+++ b/dom/canvas/ImageData.cpp
@@ -101,10 +101,39 @@ void ImageData::DropData() {
   }
 }
 
 bool ImageData::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
                            JS::MutableHandle<JSObject*> aReflector) {
   return ImageData_Binding::Wrap(aCx, this, aGivenProto, aReflector);
 }
 
+// static
+already_AddRefed<ImageData> ImageData::ReadStructuredClone(
+    JSContext* aCx, nsIGlobalObject* aGlobal,
+    JSStructuredCloneReader* aReader) {
+  // Read the information out of the stream.
+  uint32_t width, height;
+  JS::Rooted<JS::Value> dataArray(aCx);
+  if (!JS_ReadUint32Pair(aReader, &width, &height) ||
+      !JS_ReadTypedArray(aReader, &dataArray)) {
+    return nullptr;
+  }
+  MOZ_ASSERT(dataArray.isObject());
+
+  RefPtr<ImageData> imageData =
+      new ImageData(width, height, dataArray.toObject());
+  return imageData.forget();
+}
+
+bool ImageData::WriteStructuredClone(JSContext* aCx,
+                                     JSStructuredCloneWriter* aWriter) const {
+  JS::Rooted<JS::Value> arrayValue(aCx, JS::ObjectValue(*GetDataObject()));
+  if (!JS_WrapValue(aCx, &arrayValue)) {
+    return false;
+  }
+
+  return JS_WriteUint32Pair(aWriter, Width(), Height()) &&
+         JS_WriteTypedArray(aWriter, arrayValue);
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/canvas/ImageData.h
+++ b/dom/canvas/ImageData.h
@@ -10,16 +10,19 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/TypedArray.h"
 #include <stdint.h>
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupportsImpl.h"
 #include "js/RootingAPI.h"
+#include "js/StructuredClone.h"
+
+class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
 class ImageData final : public nsISupports {
   ~ImageData() { DropData(); }
 
  public:
@@ -46,16 +49,23 @@ class ImageData final : public nsISuppor
   void GetData(JSContext* cx, JS::MutableHandle<JSObject*> aData) const {
     aData.set(GetDataObject());
   }
   JSObject* GetDataObject() const { return mData; }
 
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
                   JS::MutableHandle<JSObject*> aReflector);
 
+  //[Serializable] implementation
+  static already_AddRefed<ImageData> ReadStructuredClone(
+      JSContext* aCx, nsIGlobalObject* aGlobal,
+      JSStructuredCloneReader* aReader);
+  bool WriteStructuredClone(JSContext* aCx,
+                            JSStructuredCloneWriter* aWriter) const;
+
  private:
   void HoldData();
   void DropData();
 
   ImageData() = delete;
 
   uint32_t mWidth, mHeight;
   JS::Heap<JSObject*> mData;
--- a/dom/webidl/ImageData.webidl
+++ b/dom/webidl/ImageData.webidl
@@ -7,17 +7,18 @@
  * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA.
  * You are granted a license to use, reproduce and create derivative works of this document.
  */
 
 [Constructor(unsigned long sw, unsigned long sh),
  Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh),
- Exposed=(Window,Worker)]
+ Exposed=(Window,Worker),
+ Serializable]
 interface ImageData {
  [Constant]
  readonly attribute unsigned long width;
  [Constant]
  readonly attribute unsigned long height;
  [Constant, StoreInSlot]
  readonly attribute Uint8ClampedArray data;
 };