Title: [230828] trunk
Revision
230828
Author
commit-qu...@webkit.org
Date
2018-04-19 16:59:50 -0700 (Thu, 19 Apr 2018)

Log Message

REGRESSION(r227340): ArrayBuffers were not being serialized when sent via MessagePorts
https://bugs.webkit.org/show_bug.cgi?id=184254
<rdar://problem/39140200>

Patch by Tadeu Zagallo <tzaga...@apple.com> on 2018-04-19
Reviewed by Daniel Bates.

Source/_javascript_Core:

Expose an extra constructor of ArrayBufferContents in order to be able to decode SerializedScriptValues.

* runtime/ArrayBuffer.h:
(JSC::ArrayBufferContents::ArrayBufferContents):

Source/WebCore:

Add a new encoding method to SerializedScriptValue that includes ArrayBuffers.

Test: workers/message-port.html

* bindings/js/SerializedScriptValue.h:
(WebCore::SerializedScriptValue::encode const):
(WebCore::SerializedScriptValue::decode):
* dom/messageports/MessageWithMessagePorts.h:
(WebCore::MessageWithMessagePorts::encode const):
(WebCore::MessageWithMessagePorts::decode):

LayoutTests:

The regression test provided with the bug report verifies that the ArrayBuffer is properly
serialized - before, the whole data object would be null.
Test case provided by Yann Cabon <yca...@esri.com> as part of the bug report.

* workers/message-port-expected.txt: Added.
* workers/message-port.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (230827 => 230828)


--- trunk/LayoutTests/ChangeLog	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/LayoutTests/ChangeLog	2018-04-19 23:59:50 UTC (rev 230828)
@@ -1,3 +1,18 @@
+2018-04-19  Tadeu Zagallo  <tzaga...@apple.com>
+
+        REGRESSION(r227340): ArrayBuffers were not being serialized when sent via MessagePorts
+        https://bugs.webkit.org/show_bug.cgi?id=184254
+        <rdar://problem/39140200>
+
+        Reviewed by Daniel Bates.
+
+        The regression test provided with the bug report verifies that the ArrayBuffer is properly
+        serialized - before, the whole data object would be null.
+        Test case provided by Yann Cabon <yca...@esri.com> as part of the bug report.
+
+        * workers/message-port-expected.txt: Added.
+        * workers/message-port.html: Added.
+
 2018-04-19  Eric Carlson  <eric.carl...@apple.com>
 
         Runtime logging during GC can cause crash

Added: trunk/LayoutTests/workers/message-port-expected.txt (0 => 230828)


--- trunk/LayoutTests/workers/message-port-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/workers/message-port-expected.txt	2018-04-19 23:59:50 UTC (rev 230828)
@@ -0,0 +1,12 @@
+Sends ArrayBuffers through MessagePorts.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS array[0] contains 3.141592653589793
+PASS successfully transferred array of length 0
+PASS successfully transferred array of length 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/workers/message-port.html (0 => 230828)


--- trunk/LayoutTests/workers/message-port.html	                        (rev 0)
+++ trunk/LayoutTests/workers/message-port.html	2018-04-19 23:59:50 UTC (rev 230828)
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+description("Sends ArrayBuffers through MessagePorts.");
+window.jsTestIsAsync = true;
+
+function test(data, postMessage, checkResult) {
+    return new Promise(function (resolve) {
+        const channel = new MessageChannel();
+
+        channel.port1._onmessage_ = event => {
+            if (!event.data)
+                debug("message data null!");
+            postMessage(event.data, event.target);
+        };
+
+        channel.port2._onmessage_ = event => {
+            checkResult(event.data);
+            resolve();
+        };
+
+        postMessage(data, channel.port2);
+    });
+}
+
+function testEmptyArray(buf) {
+    const array = new Float64Array(buf);
+    if (!array.length)
+        testPassed(`successfully transferred array of length 0`);
+    else
+        testFailed(`${array} should be a Float64Array of length 0`);
+}
+
+const array = new Float64Array([Math.PI]);
+const emptyArray = new Float64Array();
+const emptyArray2 = new Float64Array();
+
+test(
+    { buf: [array.buffer, emptyArray.buffer] },
+    (data, port) => port.postMessage({ buf: data.buf }, data.buf),
+    data ="" {
+        const array = new Float64Array(data.buf[0]);
+        if (array[0] === Math.PI)
+            testPassed(`array[0] contains ${Math.PI}`);
+        else
+            testFailed(`${array[0]} should be ${Math.PI}`);
+
+        testEmptyArray(data.buf[1]);
+    }
+).then(() =>
+    test(
+        { buf: emptyArray2.buffer },
+        (data, port) => port.postMessage({ buf: data.buf }, [data.buf]),
+        data ="" testEmptyArray(data.buf)
+    ),
+).then(finishJSTest);
+</script>
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (230827 => 230828)


--- trunk/Source/_javascript_Core/ChangeLog	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-04-19 23:59:50 UTC (rev 230828)
@@ -1,3 +1,16 @@
+2018-04-19  Tadeu Zagallo  <tzaga...@apple.com>
+
+        REGRESSION(r227340): ArrayBuffers were not being serialized when sent via MessagePorts
+        https://bugs.webkit.org/show_bug.cgi?id=184254
+        <rdar://problem/39140200>
+
+        Reviewed by Daniel Bates.
+
+        Expose an extra constructor of ArrayBufferContents in order to be able to decode SerializedScriptValues.
+
+        * runtime/ArrayBuffer.h:
+        (JSC::ArrayBufferContents::ArrayBufferContents):
+
 2018-04-19  Mark Lam  <mark....@apple.com>
 
         Apply pointer profiling to Signal pointers.

Modified: trunk/Source/_javascript_Core/runtime/ArrayBuffer.h (230827 => 230828)


--- trunk/Source/_javascript_Core/runtime/ArrayBuffer.h	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/_javascript_Core/runtime/ArrayBuffer.h	2018-04-19 23:59:50 UTC (rev 230828)
@@ -59,6 +59,7 @@
     WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
 public:
     JS_EXPORT_PRIVATE ArrayBufferContents();
+    JS_EXPORT_PRIVATE ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&&);
     
     JS_EXPORT_PRIVATE ArrayBufferContents(ArrayBufferContents&&);
     JS_EXPORT_PRIVATE ArrayBufferContents& operator=(ArrayBufferContents&&);
@@ -73,10 +74,8 @@
     unsigned sizeInBytes() const { return m_sizeInBytes; }
     
     bool isShared() const { return m_shared; }
-
+    
 private:
-    ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&&);
-    
     void destroy();
     void reset();
 

Modified: trunk/Source/WebCore/ChangeLog (230827 => 230828)


--- trunk/Source/WebCore/ChangeLog	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/WebCore/ChangeLog	2018-04-19 23:59:50 UTC (rev 230828)
@@ -1,3 +1,22 @@
+2018-04-19  Tadeu Zagallo  <tzaga...@apple.com>
+
+        REGRESSION(r227340): ArrayBuffers were not being serialized when sent via MessagePorts
+        https://bugs.webkit.org/show_bug.cgi?id=184254
+        <rdar://problem/39140200>
+
+        Reviewed by Daniel Bates.
+
+        Add a new encoding method to SerializedScriptValue that includes ArrayBuffers.
+
+        Test: workers/message-port.html
+
+        * bindings/js/SerializedScriptValue.h:
+        (WebCore::SerializedScriptValue::encode const):
+        (WebCore::SerializedScriptValue::decode):
+        * dom/messageports/MessageWithMessagePorts.h:
+        (WebCore::MessageWithMessagePorts::encode const):
+        (WebCore::MessageWithMessagePorts::decode):
+
 2018-04-19  David Kilzer  <ddkil...@apple.com>
 
         Enable Objective-C weak references

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (230827 => 230828)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2018-04-19 23:59:50 UTC (rev 230828)
@@ -3169,6 +3169,12 @@
 {
 }
 
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray)
+    : m_data(WTFMove(buffer))
+    , m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray))
+{
+}
+
 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers
 #if ENABLE(WEBASSEMBLY)
         , std::unique_ptr<WasmModuleArray> wasmModulesArray

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.h (230827 => 230828)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.h	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.h	2018-04-19 23:59:50 UTC (rev 230828)
@@ -33,6 +33,7 @@
 #include <_javascript_Core/Strong.h>
 #include <wtf/Forward.h>
 #include <wtf/Function.h>
+#include <wtf/Gigacage.h>
 #include <wtf/text/WTFString.h>
 
 typedef const struct OpaqueJSContext* JSContextRef;
@@ -101,10 +102,14 @@
     }
     const Vector<uint8_t>& toWireBytes() const { return m_data; }
 
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static RefPtr<SerializedScriptValue> decode(Decoder&);
+
     WEBCORE_EXPORT ~SerializedScriptValue();
 
 private:
     WEBCORE_EXPORT SerializedScriptValue(Vector<unsigned char>&&);
+    WEBCORE_EXPORT SerializedScriptValue(Vector<unsigned char>&&, std::unique_ptr<ArrayBufferContentsArray>);
     SerializedScriptValue(Vector<unsigned char>&&, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers
 #if ENABLE(WEBASSEMBLY)
         , std::unique_ptr<WasmModuleArray>
@@ -121,4 +126,62 @@
     Vector<String> m_blobURLs;
 };
 
+template<class Encoder>
+void SerializedScriptValue::encode(Encoder& encoder) const
+{
+    encoder << m_data;
+
+    auto hasArray = m_arrayBufferContentsArray && m_arrayBufferContentsArray->size();
+    encoder << hasArray;
+
+    if (!hasArray)
+        return;
+
+    encoder << static_cast<uint64_t>(m_arrayBufferContentsArray->size());
+    for (const auto &arrayBufferContents : *m_arrayBufferContentsArray) {
+        encoder << arrayBufferContents.sizeInBytes();
+        encoder.encodeFixedLengthData(static_cast<const uint8_t*>(arrayBufferContents.data()), arrayBufferContents.sizeInBytes(), 1);
+    }
 }
+
+template<class Decoder>
+RefPtr<SerializedScriptValue> SerializedScriptValue::decode(Decoder& decoder)
+{
+    Vector<uint8_t> data;
+    if (!decoder.decode(data))
+        return nullptr;
+
+    bool hasArray;
+    if (!decoder.decode(hasArray))
+        return nullptr;
+
+    if (!hasArray)
+        return adoptRef(*new SerializedScriptValue(WTFMove(data)));
+
+    uint64_t arrayLength;
+    if (!decoder.decode(arrayLength))
+        return nullptr;
+    ASSERT(arrayLength);
+
+    auto arrayBufferContentsArray = std::make_unique<ArrayBufferContentsArray>();
+    while (arrayLength--) {
+        unsigned bufferSize;
+        if (!decoder.decode(bufferSize))
+            return nullptr;
+
+        auto buffer = Gigacage::tryMalloc(Gigacage::Primitive, bufferSize);
+        auto destructor = [] (void* ptr) {
+            Gigacage::free(Gigacage::Primitive, ptr);
+        };
+        if (!decoder.decodeFixedLengthData(static_cast<uint8_t*>(buffer), bufferSize, 1)) {
+            destructor(buffer);
+            return nullptr;
+        }
+        arrayBufferContentsArray->append({ buffer, bufferSize, WTFMove(destructor) });
+    }
+
+    return adoptRef(*new SerializedScriptValue(WTFMove(data), WTFMove(arrayBufferContentsArray)));
+}
+
+
+}

Modified: trunk/Source/WebCore/dom/messageports/MessageWithMessagePorts.h (230827 => 230828)


--- trunk/Source/WebCore/dom/messageports/MessageWithMessagePorts.h	2018-04-19 23:51:56 UTC (rev 230827)
+++ trunk/Source/WebCore/dom/messageports/MessageWithMessagePorts.h	2018-04-19 23:59:50 UTC (rev 230828)
@@ -48,7 +48,7 @@
 void MessageWithMessagePorts::encode(Encoder& encoder) const
 {
     ASSERT(message);
-    encoder << message->toWireBytes() << transferredPorts;
+    encoder << *message << transferredPorts;
 }
 
 template<class Decoder>
@@ -56,14 +56,13 @@
 {
     MessageWithMessagePorts result;
 
-    Vector<uint8_t> wireBytes;
-    if (!decoder.decode(wireBytes))
+    result.message = SerializedScriptValue::decode(decoder);
+    if (!result.message)
         return std::nullopt;
 
     if (!decoder.decode(result.transferredPorts))
         return std::nullopt;
 
-    result.message = SerializedScriptValue::createFromWireBytes(WTFMove(wireBytes));
     return result;
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to