⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 238507 in webkit


Ignore:
Timestamp:
Nov 26, 2018, 11:55:30 AM (8 years ago)
Author:
Wenson Hsieh
Message:

CompletionHandler-based async IPC messages only work when the completion handler takes a single argument
https://bugs.webkit.org/show_bug.cgi?id=191965

Reviewed by Tim Horton.

Teach messages.py to handle the case where an async IPC completion handler takes no arguments, or takes more
than a single argument. Currently, the generated code attempts to wrap all arguments in a WTFMove(*~), but
this either results in WTFMove(*) in the case where there are no arguments, or WTFMove(*foo, *bar, *baz) in
the case where there are several arguments. Both of these results fail to compile.

Instead, emit completionHandler() when there are no arguments, and
completionHandler(WTFMove(*foo), WTFMove(*bar), WTFMove(*baz)) when there are multiple arguments.

Tests: TestAsyncMessageWithNoArguments

TestAsyncMessageWithMultipleArguments

  • Scripts/webkit/MessageReceiverSuperclass-expected.cpp:

(Messages::WebPage::TestAsyncMessageWithNoArguments::callReply):
(Messages::WebPage::TestAsyncMessageWithNoArguments::cancelReply):
(Messages::WebPage::TestAsyncMessageWithNoArguments::send):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::callReply):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::cancelReply):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::send):
(WebKit::WebPage::didReceiveMessage):

  • Scripts/webkit/MessagesSuperclass-expected.h:

(Messages::WebPage::TestAsyncMessageWithNoArguments::receiverName):
(Messages::WebPage::TestAsyncMessageWithNoArguments::name):
(Messages::WebPage::TestAsyncMessageWithNoArguments::asyncMessageReplyName):
(Messages::WebPage::TestAsyncMessageWithNoArguments::arguments const):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::receiverName):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::name):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::asyncMessageReplyName):
(Messages::WebPage::TestAsyncMessageWithMultipleArguments::arguments const):

  • Scripts/webkit/messages.py:
  • Scripts/webkit/messages_unittest.py:

Add new messages.py unit tests to cover these cases.

  • Scripts/webkit/test-superclass-messages.in:
Location:
trunk/Source/WebKit
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r238503 r238507  
     12018-11-26  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        CompletionHandler-based async IPC messages only work when the completion handler takes a single argument
     4        https://bugs.webkit.org/show_bug.cgi?id=191965
     5
     6        Reviewed by Tim Horton.
     7
     8        Teach `messages.py` to handle the case where an async IPC completion handler takes no arguments, or takes more
     9        than a single argument. Currently, the generated code attempts to wrap all arguments in a `WTFMove(*~)`, but
     10        this either results in `WTFMove(*)` in the case where there are no arguments, or `WTFMove(*foo, *bar, *baz)` in
     11        the case where there are several arguments. Both of these results fail to compile.
     12
     13        Instead, emit `completionHandler()` when there are no arguments, and
     14        `completionHandler(WTFMove(*foo), WTFMove(*bar), WTFMove(*baz))` when there are multiple arguments.
     15
     16        Tests:  TestAsyncMessageWithNoArguments
     17                TestAsyncMessageWithMultipleArguments
     18
     19        * Scripts/webkit/MessageReceiverSuperclass-expected.cpp:
     20        (Messages::WebPage::TestAsyncMessageWithNoArguments::callReply):
     21        (Messages::WebPage::TestAsyncMessageWithNoArguments::cancelReply):
     22        (Messages::WebPage::TestAsyncMessageWithNoArguments::send):
     23        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::callReply):
     24        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::cancelReply):
     25        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::send):
     26        (WebKit::WebPage::didReceiveMessage):
     27        * Scripts/webkit/MessagesSuperclass-expected.h:
     28        (Messages::WebPage::TestAsyncMessageWithNoArguments::receiverName):
     29        (Messages::WebPage::TestAsyncMessageWithNoArguments::name):
     30        (Messages::WebPage::TestAsyncMessageWithNoArguments::asyncMessageReplyName):
     31        (Messages::WebPage::TestAsyncMessageWithNoArguments::arguments const):
     32        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::receiverName):
     33        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::name):
     34        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::asyncMessageReplyName):
     35        (Messages::WebPage::TestAsyncMessageWithMultipleArguments::arguments const):
     36        * Scripts/webkit/messages.py:
     37        * Scripts/webkit/messages_unittest.py:
     38
     39        Add new `messages.py` unit tests to cover these cases.
     40
     41        * Scripts/webkit/test-superclass-messages.in:
     42
    1432018-11-26  Jeremy Jones  <jeremyj@apple.com>
    244
  • trunk/Source/WebKit/Scripts/webkit/MessageReceiverSuperclass-expected.cpp

    r237300 r238507  
    6868#endif
    6969
     70#if ENABLE(TEST_FEATURE)
     71
     72void TestAsyncMessageWithNoArguments::callReply(IPC::Decoder& decoder, CompletionHandler<void()>&& completionHandler)
     73{
     74    completionHandler();
     75}
     76
     77void TestAsyncMessageWithNoArguments::cancelReply(CompletionHandler<void()>&& completionHandler)
     78{
     79    completionHandler();
     80}
     81
     82void TestAsyncMessageWithNoArguments::send(std::unique_ptr<IPC::Encoder>&& encoder, IPC::Connection& connection)
     83{
     84    connection.sendSyncReply(WTFMove(encoder));
     85}
     86
     87#endif
     88
     89#if ENABLE(TEST_FEATURE)
     90
     91void TestAsyncMessageWithMultipleArguments::callReply(IPC::Decoder& decoder, CompletionHandler<void(bool&&, uint64_t&&)>&& completionHandler)
     92{
     93    std::optional<bool> flag;
     94    decoder >> flag;
     95    if (!flag) {
     96        ASSERT_NOT_REACHED();
     97        return;
     98    }
     99    std::optional<uint64_t> value;
     100    decoder >> value;
     101    if (!value) {
     102        ASSERT_NOT_REACHED();
     103        return;
     104    }
     105    completionHandler(WTFMove(*flag), WTFMove(*value));
     106}
     107
     108void TestAsyncMessageWithMultipleArguments::cancelReply(CompletionHandler<void(bool&&, uint64_t&&)>&& completionHandler)
     109{
     110    completionHandler({ }, { });
     111}
     112
     113void TestAsyncMessageWithMultipleArguments::send(std::unique_ptr<IPC::Encoder>&& encoder, IPC::Connection& connection, bool flag, uint64_t value)
     114{
     115    *encoder << flag;
     116    *encoder << value;
     117    connection.sendSyncReply(WTFMove(encoder));
     118}
     119
     120#endif
     121
    70122void TestDelayedMessage::send(std::unique_ptr<IPC::Encoder>&& encoder, IPC::Connection& connection, const std::optional<WebKit::TestClassName>& optionalReply)
    71123{
     
    92144    }
    93145#endif
     146#if ENABLE(TEST_FEATURE)
     147    if (decoder.messageName() == Messages::WebPage::TestAsyncMessageWithNoArguments::name()) {
     148        IPC::handleMessageAsync<Messages::WebPage::TestAsyncMessageWithNoArguments>(connection, decoder, this, &WebPage::testAsyncMessageWithNoArguments);
     149        return;
     150    }
     151#endif
     152#if ENABLE(TEST_FEATURE)
     153    if (decoder.messageName() == Messages::WebPage::TestAsyncMessageWithMultipleArguments::name()) {
     154        IPC::handleMessageAsync<Messages::WebPage::TestAsyncMessageWithMultipleArguments>(connection, decoder, this, &WebPage::testAsyncMessageWithMultipleArguments);
     155        return;
     156    }
     157#endif
    94158    WebPageBase::didReceiveMessage(connection, decoder);
    95159}
  • trunk/Source/WebKit/Scripts/webkit/MessagesSuperclass-expected.h

    r237300 r238507  
    100100#endif
    101101
     102#if ENABLE(TEST_FEATURE)
     103class TestAsyncMessageWithNoArguments {
     104public:
     105    typedef std::tuple<> Arguments;
     106
     107    static IPC::StringReference receiverName() { return messageReceiverName(); }
     108    static IPC::StringReference name() { return IPC::StringReference("TestAsyncMessageWithNoArguments"); }
     109    static const bool isSync = false;
     110
     111    static void callReply(IPC::Decoder&, CompletionHandler<void()>&&);
     112    static void cancelReply(CompletionHandler<void()>&&);
     113    static IPC::StringReference asyncMessageReplyName() { return { "TestAsyncMessageWithNoArgumentsReply" }; }
     114    using AsyncReply = CompletionHandler<void()>;
     115    static void send(std::unique_ptr<IPC::Encoder>&&, IPC::Connection&);
     116    typedef std::tuple<> Reply;
     117    const Arguments& arguments() const
     118    {
     119        return m_arguments;
     120    }
     121
     122private:
     123    Arguments m_arguments;
     124};
     125#endif
     126
     127#if ENABLE(TEST_FEATURE)
     128class TestAsyncMessageWithMultipleArguments {
     129public:
     130    typedef std::tuple<> Arguments;
     131
     132    static IPC::StringReference receiverName() { return messageReceiverName(); }
     133    static IPC::StringReference name() { return IPC::StringReference("TestAsyncMessageWithMultipleArguments"); }
     134    static const bool isSync = false;
     135
     136    static void callReply(IPC::Decoder&, CompletionHandler<void(bool&&, uint64_t&&)>&&);
     137    static void cancelReply(CompletionHandler<void(bool&&, uint64_t&&)>&&);
     138    static IPC::StringReference asyncMessageReplyName() { return { "TestAsyncMessageWithMultipleArgumentsReply" }; }
     139    using AsyncReply = CompletionHandler<void(bool flag, uint64_t value)>;
     140    static void send(std::unique_ptr<IPC::Encoder>&&, IPC::Connection&, bool flag, uint64_t value);
     141    typedef std::tuple<bool&, uint64_t&> Reply;
     142    const Arguments& arguments() const
     143    {
     144        return m_arguments;
     145    }
     146
     147private:
     148    Arguments m_arguments;
     149};
     150#endif
     151
    102152class TestSyncMessage {
    103153public:
  • trunk/Source/WebKit/Scripts/webkit/messages.py

    r238388 r238507  
    567567                    result.append('    decoder >> %s;\n' % x.name)
    568568                    result.append('    if (!%s) {\n        ASSERT_NOT_REACHED();\n        return;\n    }\n' % x.name)
    569                 result.append('    completionHandler(WTFMove(*%s));\n}\n\n' % (', *'.join(x.name for x in message.reply_parameters)))
     569                result.append('    completionHandler(')
     570                if len(message.reply_parameters):
     571                    result.append('WTFMove(*%s)' % ('), WTFMove(*'.join(x.name for x in message.reply_parameters)))
     572                result.append(');\n}\n\n')
    570573                result.append('void %s::cancelReply(CompletionHandler<void(%s)>&& completionHandler)\n{\n    completionHandler(' % move_parameters)
    571574                result.append(', '.join(['{ }' for x in message.reply_parameters]))
  • trunk/Source/WebKit/Scripts/webkit/messages_unittest.py

    r237303 r238507  
    256256        },
    257257        {
     258            'name': 'TestAsyncMessageWithNoArguments',
     259            'parameters': (),
     260            'reply_parameters': (),
     261            'conditions': ('ENABLE(TEST_FEATURE)'),
     262        },
     263        {
     264            'name': 'TestAsyncMessageWithMultipleArguments',
     265            'parameters': (),
     266            'reply_parameters': (
     267                ('bool', 'flag'),
     268                ('uint64_t', 'value'),
     269            ),
     270            'conditions': ('ENABLE(TEST_FEATURE)'),
     271        },
     272        {
    258273            'name': 'TestSyncMessage',
    259274            'parameters': (
  • trunk/Source/WebKit/Scripts/webkit/test-superclass-messages.in

    r237300 r238507  
    2525#if ENABLE(TEST_FEATURE)
    2626    TestAsyncMessage(enum:bool WebKit::TestTwoStateEnum twoStateEnum) -> (uint64_t result) Async
     27    TestAsyncMessageWithNoArguments() -> () Async
     28    TestAsyncMessageWithMultipleArguments() -> (bool flag, uint64_t value) Async
    2729#endif
    2830    TestSyncMessage(uint32_t param) -> (uint8_t reply) Sync
Note: See TracChangeset for help on using the changeset viewer.