Commit 58ebea75 authored by Scott Graham's avatar Scott Graham Committed by Commit Bot

fuchsia: FIDL JS struct support

Now supporting defining and passing structs from JS -> C++.

Bug: 883496
Change-Id: Ib1baf5d435f9e936393e31871f12e71f6ed79f33
Reviewed-on: https://chromium-review.googlesource.com/c/1244891
Commit-Queue: Scott Graham <scottmg@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600497}
parent 9b2ecb85
...@@ -113,8 +113,8 @@ class Compiler(object): ...@@ -113,8 +113,8 @@ class Compiler(object):
self._CompileEnum(e) self._CompileEnum(e)
if self.fidl.union_declarations: if self.fidl.union_declarations:
raise NotImplementedError() raise NotImplementedError()
if self.fidl.struct_declarations: for s in self.fidl.struct_declarations:
raise NotImplementedError() self._CompileStruct(s)
for i in self.fidl.interface_declarations: for i in self.fidl.interface_declarations:
self._CompileInterface(i) self._CompileInterface(i)
...@@ -150,6 +150,64 @@ const %(name)s = { ...@@ -150,6 +150,64 @@ const %(name)s = {
self.f.write('};\n') self.f.write('};\n')
self.f.write('const _kTT_%(name)s = _kTT_%(type)s;\n\n' % data) self.f.write('const _kTT_%(name)s = _kTT_%(type)s;\n\n' % data)
def _CompileStruct(self, struct):
compound = _ParseCompoundIdentifier(struct.name)
name = _CompileCompoundIdentifier(compound)
param_names = [_ChangeIfReserved(x.name) for x in struct.members]
# TODO(crbug.com/883496): @param and types.
self.f.write('''/**
* @constructor
* @struct
*/
function %(name)s(%(param_names)s) {
''' % { 'name': name,
'param_names': ', '.join(param_names) })
for member in struct.members:
member_name = _ChangeIfReserved(member.name)
value = '%(member_name)s'
if member.maybe_default_value:
value = ('(%(member_name)s !== undefined) ? %(member_name)s : ' +
_CompileConstant(member.maybe_default_value))
self.f.write((' this.%(member_name)s = ' + value + ';\n') %
{ 'member_name': member_name })
self.f.write('}\n\n')
self.f.write(
'''const _kTT_%(name)s = {
enc: function(e, o, v) {
''' % { 'name': name })
for member in struct.members:
element_ttname = self._CompileType(member.type)
self.f.write(
' _kTT_%(element_ttname)s.enc('
'e, o + %(offset)s, v.%(member_name)s);\n' % {
'element_ttname': element_ttname,
'offset': member.offset,
'member_name': _ChangeIfReserved(member.name)
})
self.f.write(
''' },
dec: function(d, o) {
''')
for member in struct.members:
element_ttname = self._CompileType(member.type)
self.f.write(
' var $temp_%(member_name)s = _kTT_%(element_ttname)s.dec('
'e, o + %(offset)s);\n' % {
'element_ttname': element_ttname,
'offset': member.offset,
'member_name': _ChangeIfReserved(member.name)
})
self.f.write(''' return %(name)s(%(temp_names)s);
}
};
''' % { 'name': name,
'temp_names': ', '.join(['$temp_' + x for x in param_names]) })
def _CompileType(self, t): def _CompileType(self, t):
if t.kind == TypeKind.PRIMITIVE: if t.kind == TypeKind.PRIMITIVE:
......
...@@ -121,6 +121,11 @@ $fidl_Decoder.prototype.claimHandle = function() { ...@@ -121,6 +121,11 @@ $fidl_Decoder.prototype.claimHandle = function() {
// Type tables and encoding helpers for generated Proxy code. // Type tables and encoding helpers for generated Proxy code.
const _kTT_bool = {
enc: function(e, o, v) { e.data.setInt8(o, v ? 1 : 0); },
dec: function(d, o) { return d.data.getInt8(o) != 0; },
};
const _kTT_int8 = { const _kTT_int8 = {
enc: function(e, o, v) { e.data.setInt8(o, v); }, enc: function(e, o, v) { e.data.setInt8(o, v); },
dec: function(d, o) { return d.data.getInt8(o); }, dec: function(d, o) { return d.data.getInt8(o); },
......
...@@ -156,7 +156,10 @@ TEST_F(FidlGenJsTest, CreateChannelPair) { ...@@ -156,7 +156,10 @@ TEST_F(FidlGenJsTest, CreateChannelPair) {
class TestolaImpl : public fidljstest::Testola { class TestolaImpl : public fidljstest::Testola {
public: public:
TestolaImpl() = default; TestolaImpl() {
// Don't want the default values from the C++ side.
memset(&basic_struct_, -1, sizeof(basic_struct_));
}
~TestolaImpl() override {} ~TestolaImpl() override {}
void DoSomething() override { was_do_something_called_ = true; } void DoSomething() override { was_do_something_called_ = true; }
...@@ -182,6 +185,10 @@ class TestolaImpl : public fidljstest::Testola { ...@@ -182,6 +185,10 @@ class TestolaImpl : public fidljstest::Testola {
sum(a + b); sum(a + b);
} }
void SendAStruct(fidljstest::BasicStruct basic_struct) override {
basic_struct_ = basic_struct;
}
bool was_do_something_called() const { return was_do_something_called_; } bool was_do_something_called() const { return was_do_something_called_; }
int32_t received_int() const { return received_int_; } int32_t received_int() const { return received_int_; }
const std::string& received_msg() const { return received_msg_; } const std::string& received_msg() const { return received_msg_; }
...@@ -190,6 +197,8 @@ class TestolaImpl : public fidljstest::Testola { ...@@ -190,6 +197,8 @@ class TestolaImpl : public fidljstest::Testola {
const std::string& various_msg() const { return various_msg_; } const std::string& various_msg() const { return various_msg_; }
const std::vector<uint32_t>& various_stuff() const { return various_stuff_; } const std::vector<uint32_t>& various_stuff() const { return various_stuff_; }
fidljstest::BasicStruct GetReceivedStruct() const { return basic_struct_; }
private: private:
bool was_do_something_called_ = false; bool was_do_something_called_ = false;
int32_t received_int_ = -1; int32_t received_int_ = -1;
...@@ -197,6 +206,7 @@ class TestolaImpl : public fidljstest::Testola { ...@@ -197,6 +206,7 @@ class TestolaImpl : public fidljstest::Testola {
fidljstest::Blorp various_blorp_; fidljstest::Blorp various_blorp_;
std::string various_msg_; std::string various_msg_;
std::vector<uint32_t> various_stuff_; std::vector<uint32_t> various_stuff_;
fidljstest::BasicStruct basic_struct_;
DISALLOW_COPY_AND_ASSIGN(TestolaImpl); DISALLOW_COPY_AND_ASSIGN(TestolaImpl);
}; };
...@@ -410,6 +420,42 @@ TEST_F(FidlGenJsTest, NoResponseBeforeTearDown) { ...@@ -410,6 +420,42 @@ TEST_F(FidlGenJsTest, NoResponseBeforeTearDown) {
EXPECT_FALSE(helper.Get<bool>("excepted")); EXPECT_FALSE(helper.Get<bool>("excepted"));
} }
TEST_F(FidlGenJsTest, RawReceiveFidlStructMessage) {
base::AsyncDispatcher dispatcher;
v8::Isolate* isolate = instance_->isolate();
BindingsSetupHelper helper(isolate);
TestolaImpl testola_impl;
fidl::Binding<fidljstest::Testola> binding(&testola_impl);
binding.Bind(std::move(helper.server()), &dispatcher);
// Send the data from the JS side into the channel.
std::string source = R"(
var proxy = new TestolaProxy();
proxy.$bind(testHandle);
var basicStruct = new BasicStruct(
true, -30, undefined, -789, 200, 65000, 0);
proxy.SendAStruct(basicStruct);
)";
helper.runner().Run(source, "test.js");
// Run the dispatcher to read and dispatch the response.
ASSERT_EQ(dispatcher.DispatchOrWaitUntil(zx_deadline_after(
ZX_MSEC(TestTimeouts::action_timeout().InMilliseconds()))),
ZX_OK);
fidljstest::BasicStruct received_struct = testola_impl.GetReceivedStruct();
EXPECT_EQ(received_struct.b, true);
EXPECT_EQ(received_struct.i8, -30);
EXPECT_EQ(received_struct.i16, 18); // From defaults.
EXPECT_EQ(received_struct.i32, -789);
EXPECT_EQ(received_struct.u8, 200);
EXPECT_EQ(received_struct.u16, 65000);
// Make sure this didn't get defaulted, even though it has a false-ish value.
EXPECT_EQ(received_struct.u32, 0u);
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
base::TestSuite test_suite(argc, argv); base::TestSuite test_suite(argc, argv);
......
...@@ -10,6 +10,18 @@ enum Blorp : int8 { ...@@ -10,6 +10,18 @@ enum Blorp : int8 {
GAMMA = 0x48; GAMMA = 0x48;
}; };
// A struct of basic types, some with defaults and some without to test various
// paths of the generator.
struct BasicStruct {
bool b;
int8 i8;
int16 i16 = 18;
int32 i32;
uint8 u8;
uint16 u16;
uint32 u32 = 4000000000;
};
interface Testola { interface Testola {
1: DoSomething(); 1: DoSomething();
...@@ -20,4 +32,6 @@ interface Testola { ...@@ -20,4 +32,6 @@ interface Testola {
4: VariousArgs(Blorp blorp, string:32 msg, vector<uint32> stuff); 4: VariousArgs(Blorp blorp, string:32 msg, vector<uint32> stuff);
5: WithResponse(int32 a, int32 b) -> (int32 sum); 5: WithResponse(int32 a, int32 b) -> (int32 sum);
6: SendAStruct(BasicStruct basic);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment