Title: [268946] trunk
Revision
268946
Author
[email protected]
Date
2020-10-23 17:02:45 -0700 (Fri, 23 Oct 2020)

Log Message

IPC testing API should expose ArrayBuffer for an unknown decoded argument
https://bugs.webkit.org/show_bug.cgi?id=218113

Reviewed by Darin Adler.

Source/WebKit:

Expose the decoded argument as an ArrayBuffer when it can't be encoded as a JS value.

Also make the treatment of a JS array as a tuple or a Vector explicit in argument encoding.

Test: TestWebKitAPI.IPCTestingAPI.CanInterceptAlert

* Platform/IPC/Decoder.h:
(IPC::Decoder::currentBufferPosition const): Added.
* Platform/IPC/JSIPCBinding.cpp:
(IPC::putJSValueForDecodedArgumentAtIndexOrArrayBufferIfUndefined): Added.
* Platform/IPC/JSIPCBinding.h:
(IPC::DecodedArgumentJSValueConverter): Deleted.
(IPC::putJSValueForDecodeArgumentInArray): Replaced DecodedArgumentJSValueConverter.
Take Decoder and decode each tuple argument and create a JS value at a time.
(IPC::jsValueForArgumentTuple): Deleted. Merged into jsValueForDecodedArguments.
(IPC::jsValueForDecodedArguments):
* WebProcess/WebPage/IPCTestingAPI.cpp:
(WebKit::IPCTestingAPI::VectorEncodeHelper::encode const):
(WebKit::IPCTestingAPI::encodeArrayArgument): Extracted out of encodeArgument.
(WebKit::IPCTestingAPI::encodeArgument): Treat an array as a tuple unless it's explicitly
specified that the argument's type is a Vector.

Tools:

Updated a test case to check that the unknown type produces an ArrayBuffer.

* TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm:
(IPCTestingAPI.CanInterceptAlert):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (268945 => 268946)


--- trunk/Source/WebKit/ChangeLog	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Source/WebKit/ChangeLog	2020-10-24 00:02:45 UTC (rev 268946)
@@ -1,3 +1,32 @@
+2020-10-22  Ryosuke Niwa  <[email protected]>
+
+        IPC testing API should expose ArrayBuffer for an unknown decoded argument
+        https://bugs.webkit.org/show_bug.cgi?id=218113
+
+        Reviewed by Darin Adler.
+
+        Expose the decoded argument as an ArrayBuffer when it can't be encoded as a JS value.
+
+        Also make the treatment of a JS array as a tuple or a Vector explicit in argument encoding.
+
+        Test: TestWebKitAPI.IPCTestingAPI.CanInterceptAlert
+
+        * Platform/IPC/Decoder.h:
+        (IPC::Decoder::currentBufferPosition const): Added.
+        * Platform/IPC/JSIPCBinding.cpp:
+        (IPC::putJSValueForDecodedArgumentAtIndexOrArrayBufferIfUndefined): Added.
+        * Platform/IPC/JSIPCBinding.h:
+        (IPC::DecodedArgumentJSValueConverter): Deleted.
+        (IPC::putJSValueForDecodeArgumentInArray): Replaced DecodedArgumentJSValueConverter.
+        Take Decoder and decode each tuple argument and create a JS value at a time.
+        (IPC::jsValueForArgumentTuple): Deleted. Merged into jsValueForDecodedArguments.
+        (IPC::jsValueForDecodedArguments):
+        * WebProcess/WebPage/IPCTestingAPI.cpp:
+        (WebKit::IPCTestingAPI::VectorEncodeHelper::encode const):
+        (WebKit::IPCTestingAPI::encodeArrayArgument): Extracted out of encodeArgument.
+        (WebKit::IPCTestingAPI::encodeArgument): Treat an array as a tuple unless it's explicitly
+        specified that the argument's type is a Vector.
+
 2020-10-23  Eric Carlson  <[email protected]>
 
         [Media in GPU Process] in-band metadata cues sometimes crash

Modified: trunk/Source/WebKit/Platform/IPC/Decoder.h (268945 => 268946)


--- trunk/Source/WebKit/Platform/IPC/Decoder.h	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Source/WebKit/Platform/IPC/Decoder.h	2020-10-24 00:02:45 UTC (rev 268946)
@@ -73,6 +73,7 @@
     static std::unique_ptr<Decoder> unwrapForTesting(Decoder&);
 
     const uint8_t* buffer() const { return m_buffer; }
+    size_t currentBufferPosition() const { return m_bufferPos - m_buffer; }
     size_t length() const { return m_bufferEnd - m_buffer; }
 
     WARN_UNUSED_RETURN bool isValid() const { return m_bufferPos != nullptr; }

Modified: trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp (268945 => 268946)


--- trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp	2020-10-24 00:02:45 UTC (rev 268946)
@@ -189,6 +189,22 @@
     return jsValueForDecodedArgumentRect(globalObject, value, "FloatRect");
 }
 
+bool putJSValueForDecodedArgumentAtIndexOrArrayBufferIfUndefined(JSC::JSGlobalObject* globalObject, JSC::JSArray* array, unsigned index, JSC::JSValue value, const uint8_t* buffer, size_t length)
+{
+    auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
+    if (value.isUndefined()) {
+        auto arrayBuffer = JSC::ArrayBuffer::create(buffer, length);
+        if (auto* structure = globalObject->arrayBufferStructure(arrayBuffer->sharingMode()))
+            value = JSC::JSArrayBuffer::create(globalObject->vm(), structure, WTFMove(arrayBuffer));
+    }
+
+    array->putDirectIndex(globalObject, index, value);
+    RETURN_IF_EXCEPTION(scope, false);
+
+    return true;
 }
 
+}
+
 #endif

Modified: trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h (268945 => 268946)


--- trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h	2020-10-24 00:02:45 UTC (rev 268946)
@@ -30,6 +30,7 @@
 #include "Decoder.h"
 #include "HandleMessage.h"
 #include <_javascript_Core/JSArray.h>
+#include <_javascript_Core/JSArrayBuffer.h>
 #include <_javascript_Core/JSGlobalObject.h>
 #include <_javascript_Core/JSObject.h>
 #include <_javascript_Core/ObjectConstructor.h>
@@ -107,51 +108,45 @@
     return result;
 }
 
-template<size_t remainingSize, typename... Elements>
-struct DecodedArgumentJSValueConverter {
-    static bool convert(JSC::JSGlobalObject* globalObject, JSC::JSArray* array, const std::tuple<Elements...>& tuple)
-    {
-        auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+bool putJSValueForDecodedArgumentAtIndexOrArrayBufferIfUndefined(JSC::JSGlobalObject*, JSC::JSArray*, unsigned index, JSC::JSValue, const uint8_t* buffer, size_t length);
 
-        auto jsValue = jsValueForDecodedArgumentValue(globalObject, std::get<sizeof...(Elements) - remainingSize>(tuple));
-        if (jsValue.isEmpty())
-            return false;
+template<typename... Elements>
+Optional<JSC::JSValue> putJSValueForDecodeArgumentInArray(JSC::JSGlobalObject*, IPC::Decoder&, JSC::JSArray*, size_t currentIndex, std::tuple<Elements...>*);
 
-        unsigned index = sizeof...(Elements) - remainingSize;
-        array->putDirectIndex(globalObject, index, jsValue);
-        RETURN_IF_EXCEPTION(scope, false);
+template<>
+inline Optional<JSC::JSValue> putJSValueForDecodeArgumentInArray(JSC::JSGlobalObject* globalObject, IPC::Decoder& decoder, JSC::JSArray* array, size_t currentIndex, std::tuple<>*)
+{
+    return JSC::JSValue { array };
+}
 
-        return DecodedArgumentJSValueConverter<remainingSize - 1, Elements...>::convert(globalObject, array, tuple);
-    }
-};
+template<typename T, typename... Elements>
+Optional<JSC::JSValue> putJSValueForDecodeArgumentInArray(JSC::JSGlobalObject* globalObject, IPC::Decoder& decoder, JSC::JSArray* array, size_t currentIndex, std::tuple<T, Elements...>*)
+{
+    auto startingBufferPosition = decoder.currentBufferPosition();
+    Optional<T> value;
+    decoder >> value;
+    if (!value)
+        return WTF::nullopt;
 
-template<typename... Elements>
-struct DecodedArgumentJSValueConverter<0, Elements...> {
-    static bool convert(JSC::JSGlobalObject*, JSC::JSArray*, const std::tuple<Elements...>&)
-    {
-        return true;
-    }
-};
+    auto jsValue = jsValueForDecodedArgumentValue(globalObject, *value);
+    if (jsValue.isEmpty())
+        return jsValue;
 
-template<typename... Elements>
-static JSC::JSValue jsValueForArgumentTuple(JSC::JSGlobalObject* globalObject, const std::tuple<Elements...>& tuple)
-{
-    auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
-    auto* array = JSC::constructEmptyArray(globalObject, nullptr);
-    RETURN_IF_EXCEPTION(scope, JSC::JSValue());
-    if (!DecodedArgumentJSValueConverter<sizeof...(Elements), Elements...>::convert(globalObject, array, tuple))
-        return JSC::JSValue();
-    return JSC::JSValue(array);
+    putJSValueForDecodedArgumentAtIndexOrArrayBufferIfUndefined(globalObject, array, currentIndex, jsValue,
+        decoder.buffer() + startingBufferPosition, decoder.currentBufferPosition() - startingBufferPosition);
+
+    std::tuple<Elements...>* dummyArguments = nullptr;
+    return putJSValueForDecodeArgumentInArray<Elements...>(globalObject, decoder, array, currentIndex + 1, dummyArguments);
 }
 
 template<typename T>
 static Optional<JSC::JSValue> jsValueForDecodedArguments(JSC::JSGlobalObject* globalObject, IPC::Decoder& decoder)
 {
-    Optional<typename IPC::CodingType<T>::Type> arguments;
-    decoder >> arguments;
-    if (!arguments)
-        return WTF::nullopt;
-    return jsValueForArgumentTuple(globalObject, *arguments);
+    auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+    auto* array = JSC::constructEmptyArray(globalObject, nullptr);
+    RETURN_IF_EXCEPTION(scope, JSC::JSValue());
+    typename IPC::CodingType<T>::Type* dummyArguments = nullptr;
+    return putJSValueForDecodeArgumentInArray<>(globalObject, decoder, array, 0, dummyArguments);
 }
 
 }

Modified: trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp (268945 => 268946)


--- trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp	2020-10-24 00:02:45 UTC (rev 268946)
@@ -364,8 +364,7 @@
     return true;
 }
 
-enum class ArrayMode { Tuple, Vector };
-static bool encodeArgument(IPC::Encoder&, JSIPC&, JSContextRef, JSValueRef, JSValueRef* exception, ArrayMode = ArrayMode::Tuple);
+static bool encodeArgument(IPC::Encoder&, JSIPC&, JSContextRef, JSValueRef, JSValueRef* exception);
 
 struct VectorEncodeHelper {
     Ref<JSIPC> jsIPC;
@@ -378,13 +377,50 @@
     {
         if (!success)
             return;
-        success = encodeArgument(encoder, jsIPC.get(), context, valueRef, exception, ArrayMode::Vector);
+        success = encodeArgument(encoder, jsIPC.get(), context, valueRef, exception);
     }
 };
 
-static bool encodeArgument(IPC::Encoder& encoder, JSIPC& jsIPC, JSContextRef context, JSValueRef valueRef, JSValueRef* exception, ArrayMode arrayMode)
+enum class ArrayMode { Tuple, Vector };
+static bool encodeArrayArgument(IPC::Encoder& encoder, JSIPC& jsIPC, ArrayMode arrayMode, JSContextRef context, JSValueRef valueRef, JSValueRef* exception)
 {
     auto objectRef = JSValueToObject(context, valueRef, exception);
+    ASSERT(objectRef);
+
+    auto* globalObject = toJS(context);
+    auto& vm = globalObject->vm();
+    JSC::JSLockHolder lock(vm);
+    auto scope = DECLARE_CATCH_SCOPE(globalObject->vm());
+    auto* jsObject = toJS(objectRef);
+
+    auto jsLength = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "length"_s));
+    if (scope.exception())
+        return false;
+    if (!jsLength.isNumber()) {
+        *exception = createTypeError(context, "Array length is not a number"_s);
+        return false;
+    }
+    auto length = jsLength.asNumber();
+
+    Vector<VectorEncodeHelper> vector;
+    bool success = true;
+    for (unsigned i = 0; i < length; ++i) {
+        auto itemRef = JSObjectGetPropertyAtIndex(context, objectRef, i, exception);
+        if (!itemRef)
+            return false;
+        vector.append(VectorEncodeHelper { jsIPC, context, itemRef, exception, success });
+    }
+    if (arrayMode == ArrayMode::Tuple) {
+        for (auto& item : vector)
+            item.encode(encoder);
+    } else
+        encoder << vector;
+    return success;
+}
+
+static bool encodeArgument(IPC::Encoder& encoder, JSIPC& jsIPC, JSContextRef context, JSValueRef valueRef, JSValueRef* exception)
+{
+    auto objectRef = JSValueToObject(context, valueRef, exception);
     if (!objectRef)
         return false;
 
@@ -391,6 +427,9 @@
     if (auto type = JSValueGetTypedArrayType(context, objectRef, exception); type != kJSTypedArrayTypeNone)
         return encodeTypedArray(encoder, context, objectRef, type, exception);
 
+    if (JSValueIsArray(context, objectRef))
+        return encodeArrayArgument(encoder, jsIPC, ArrayMode::Tuple, context, objectRef, exception);
+
     auto* globalObject = toJS(context);
     auto& vm = globalObject->vm();
     JSC::JSLockHolder lock(vm);
@@ -397,32 +436,6 @@
     auto scope = DECLARE_CATCH_SCOPE(globalObject->vm());
     auto* jsObject = toJS(globalObject, objectRef).getObject();
     ASSERT(jsObject);
-    if (JSValueIsArray(context, objectRef)) {
-        auto jsLength = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "length"_s));
-        if (scope.exception())
-            return false;
-        if (!jsLength.isNumber()) {
-            *exception = createTypeError(context, "Array length is not a number"_s);
-            return false;
-        }
-        auto length = jsLength.asNumber();
-
-        Vector<VectorEncodeHelper> vector;
-        bool success = true;
-        for (unsigned i = 0; i < length; ++i) {
-            auto itemRef = JSObjectGetPropertyAtIndex(context, objectRef, i, exception);
-            if (!itemRef)
-                return false;
-            vector.append(VectorEncodeHelper { jsIPC, context, itemRef, exception, success });
-        }
-        if (arrayMode == ArrayMode::Tuple) {
-            for (auto& item : vector)
-                item.encode(encoder);
-        } else
-            encoder << vector;
-        return success;
-    }
-
     auto jsType = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "type"_s));
     if (scope.exception())
         return false;
@@ -477,6 +490,14 @@
     if (scope.exception())
         return false;
 
+    if (type == "Vector") {
+        if (!jsValue.isObject() || !jsValue.inherits<JSC::JSArray>(vm)) {
+            *exception = createTypeError(context, "Vector value must be an array"_s);
+            return false;
+        }
+        return encodeArrayArgument(encoder, jsIPC, ArrayMode::Vector, context, toRef(globalObject, jsValue), exception);
+    }
+
     if (type == "String") {
         if (jsValue.isUndefinedOrNull()) {
             encoder << String { };

Modified: trunk/Tools/ChangeLog (268945 => 268946)


--- trunk/Tools/ChangeLog	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Tools/ChangeLog	2020-10-24 00:02:45 UTC (rev 268946)
@@ -1,3 +1,15 @@
+2020-10-22  Ryosuke Niwa  <[email protected]>
+
+        IPC testing API should expose ArrayBuffer for an unknown decoded argument
+        https://bugs.webkit.org/show_bug.cgi?id=218113
+
+        Reviewed by Darin Adler.
+
+        Updated a test case to check that the unknown type produces an ArrayBuffer.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm:
+        (IPCTestingAPI.CanInterceptAlert):
+
 2020-10-22  Darin Adler  <[email protected]>
 
         REGRESSION(r266295): DOMSelection's addRange and containsNode behave incorrectly when selection crosses shadow boundaries

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm (268945 => 268946)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm	2020-10-23 23:09:03 UTC (rev 268945)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm	2020-10-24 00:02:45 UTC (rev 268946)
@@ -222,7 +222,12 @@
     EXPECT_STREQ([alertMessage UTF8String], "ok");
     EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages = messages.filter((message) => message.name == IPC.messages.WebPageProxy_RunJavaScriptAlert.name); messages.length"].UTF8String, "1");
     EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages[0].description"].UTF8String, "WebPageProxy_RunJavaScriptAlert");
-    EXPECT_EQ([webView stringByEvaluatingJavaScript:@"messages[0].arguments.length"].intValue, 3);
+    EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args = messages[0].arguments; args.length"].intValue, 3);
+    EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[0].type"].UTF8String, "uint64_t");
+    EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args[0].value"].intValue, [webView stringByEvaluatingJavaScript:@"IPC.frameID.toString()"].intValue);
+    EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args[1] instanceof ArrayBuffer"].boolValue, YES);
+    EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[2].type"].UTF8String, "String");
+    EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[2].value"].UTF8String, "ok");
     EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"typeof(messages[0].syncRequestID)"].UTF8String, "number");
     EXPECT_EQ([webView stringByEvaluatingJavaScript:@"messages[0].destinationID"].intValue,
         [webView stringByEvaluatingJavaScript:@"IPC.webPageProxyID.toString()"].intValue);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to