summaryrefslogtreecommitdiffstats
path: root/mojo/public
diff options
context:
space:
mode:
authorrockot <rockot@chromium.org>2014-11-21 17:51:49 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-22 01:52:09 +0000
commit46da0c1f3810737c10c40c64a244991509a15c0e (patch)
tree0924244effcc1e79054e65d6550706116124d4c8 /mojo/public
parentfa8ed5bdb9f2f5f917a2e2d7adbf3ec9599f675e (diff)
downloadchromium_src-46da0c1f3810737c10c40c64a244991509a15c0e.zip
chromium_src-46da0c1f3810737c10c40c64a244991509a15c0e.tar.gz
chromium_src-46da0c1f3810737c10c40c64a244991509a15c0e.tar.bz2
Update mojo sdk to rev 5aa6dbdccf1950daf0cd3014bf763f35899bccf9
BUG=433814 Review URL: https://codereview.chromium.org/748113004 Cr-Commit-Position: refs/heads/master@{#305339}
Diffstat (limited to 'mojo/public')
-rw-r--r--mojo/public/VERSION2
-rw-r--r--mojo/public/cpp/bindings/binding.h9
-rw-r--r--mojo/public/cpp/bindings/lib/map_serialization.h14
-rw-r--r--mojo/public/cpp/bindings/strong_binding.h27
-rw-r--r--mojo/public/cpp/bindings/tests/map_unittest.cc179
-rw-r--r--mojo/public/cpp/system/tests/macros_unittest.cc2
-rw-r--r--mojo/public/cpp/utility/lib/run_loop.cc2
-rw-r--r--mojo/public/dart/BUILD.gn2
-rw-r--r--mojo/public/dart/bindings.dart3
-rw-r--r--mojo/public/dart/mojo_init.dart4
-rw-r--r--mojo/public/dart/src/client.dart103
-rw-r--r--mojo/public/dart/src/codec.dart41
-rw-r--r--mojo/public/dart/src/handle.dart47
-rw-r--r--mojo/public/dart/src/handle_watcher.dart44
-rw-r--r--mojo/public/dart/src/interface.dart86
-rw-r--r--mojo/public/dart/src/mojo_dart_core.cc73
-rw-r--r--mojo/public/dart/src/types.dart25
-rw-r--r--mojo/public/interfaces/bindings/tests/test_structs.mojom5
-rw-r--r--mojo/public/js/connection.js68
-rw-r--r--mojo/public/js/struct_unittests.js27
-rw-r--r--mojo/public/mojo_application.gni2
-rw-r--r--mojo/public/python/mojo/bindings/reflection.py28
-rwxr-xr-xmojo/public/sky/convert_amd_modules_to_sky.py6
-rw-r--r--mojo/public/tools/bindings/generators/dart_templates/enum_definition.tmpl12
-rw-r--r--mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl107
-rw-r--r--mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl15
-rw-r--r--mojo/public/tools/bindings/generators/dart_templates/module_definition.tmpl20
-rw-r--r--mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl74
-rw-r--r--mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl56
-rw-r--r--mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl3
-rw-r--r--mojo/public/tools/bindings/generators/js_templates/module.sky.tmpl1
-rw-r--r--mojo/public/tools/bindings/generators/mojom_dart_generator.py295
-rw-r--r--mojo/public/tools/bindings/generators/mojom_js_generator.py9
-rw-r--r--mojo/public/tools/bindings/mojom.gni10
-rwxr-xr-xmojo/public/tools/bindings/mojom_bindings_generator.py5
-rw-r--r--mojo/public/tools/bindings/pylib/mojom/generate/data.py14
-rwxr-xr-xmojo/public/tools/download_shell_binary.py34
37 files changed, 1195 insertions, 259 deletions
diff --git a/mojo/public/VERSION b/mojo/public/VERSION
index 3a8f9d8..282b862 100644
--- a/mojo/public/VERSION
+++ b/mojo/public/VERSION
@@ -1 +1 @@
-e01f9a49449381a5eb430c1fd88bf2cae73ec35a \ No newline at end of file
+5aa6dbdccf1950daf0cd3014bf763f35899bccf9 \ No newline at end of file
diff --git a/mojo/public/cpp/bindings/binding.h b/mojo/public/cpp/bindings/binding.h
index 2c4c9ce..72dbde3 100644
--- a/mojo/public/cpp/bindings/binding.h
+++ b/mojo/public/cpp/bindings/binding.h
@@ -34,7 +34,6 @@ namespace mojo {
// private:
// Binding<Foo> binding_;
// };
-//
template <typename Interface>
class Binding : public ErrorHandler {
public:
@@ -106,6 +105,11 @@ class Binding : public ErrorHandler {
return internal_router_->WaitForIncomingMessage();
}
+ void Close() {
+ MOJO_DCHECK(internal_router_);
+ internal_router_->CloseMessagePipe();
+ }
+
void set_error_handler(ErrorHandler* error_handler) {
error_handler_ = error_handler;
}
@@ -118,6 +122,9 @@ class Binding : public ErrorHandler {
Interface* impl() { return impl_; }
Client* client() { return proxy_; }
+
+ bool is_bound() const { return !!internal_router_; }
+
// Exposed for testing, should not generally be used.
internal::Router* internal_router() { return internal_router_; }
diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h
index 4525a00..fba8165 100644
--- a/mojo/public/cpp/bindings/lib/map_serialization.h
+++ b/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -52,10 +52,18 @@ struct MapSerializer<ScopedHandleBase<H>, H, true> {
static size_t GetItemSize(const H& item) { return 0; }
};
+// This template must only apply to pointer mojo entity (structs and arrays).
+// This is done by ensuring that WrapperTraits<S>::DataType is a pointer.
template <typename S>
-struct MapSerializer<S, typename S::Data_*, true> {
+struct MapSerializer<
+ S,
+ typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value,
+ typename WrapperTraits<S>::DataType>::type,
+ true> {
+ typedef
+ typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data;
static size_t GetBaseArraySize(size_t count) {
- return count * sizeof(internal::StructPointer<typename S::Data_>);
+ return count * sizeof(StructPointer<S_Data>);
}
static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); }
};
@@ -63,7 +71,7 @@ struct MapSerializer<S, typename S::Data_*, true> {
template <>
struct MapSerializer<String, String_Data*, false> {
static size_t GetBaseArraySize(size_t count) {
- return count * sizeof(internal::StringPointer);
+ return count * sizeof(StringPointer);
}
static size_t GetItemSize(const String& item) {
return GetSerializedSize_(item);
diff --git a/mojo/public/cpp/bindings/strong_binding.h b/mojo/public/cpp/bindings/strong_binding.h
index 106b282..73b43b3 100644
--- a/mojo/public/cpp/bindings/strong_binding.h
+++ b/mojo/public/cpp/bindings/strong_binding.h
@@ -5,6 +5,8 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
+#include <assert.h>
+
#include "mojo/public/c/environment/async_waiter.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/error_handler.h"
@@ -25,8 +27,8 @@ namespace mojo {
//
// class StronglyBound : public Foo {
// public:
-// explicit StronglyBound(ScopedMessagePipeHandle handle)
-// : binding_(this, handle.Pass()) {}
+// explicit StronglyBound(InterfaceRequest<Foo> request)
+// : binding_(this, request.Pass()) {}
//
// // Foo implementation here
//
@@ -67,6 +69,27 @@ class StrongBinding : public ErrorHandler {
~StrongBinding() override {}
+ void Bind(
+ ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ assert(!binding_.is_bound());
+ binding_.Bind(handle.Pass(), waiter);
+ }
+
+ void Bind(
+ InterfacePtr<Interface>* ptr,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ assert(!binding_.is_bound());
+ binding_.Bind(ptr, waiter);
+ }
+
+ void Bind(
+ InterfaceRequest<Interface> request,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ assert(!binding_.is_bound());
+ binding_.Bind(request.Pass(), waiter);
+ }
+
bool WaitForIncomingMethodCall() {
return binding_.WaitForIncomingMethodCall();
}
diff --git a/mojo/public/cpp/bindings/tests/map_unittest.cc b/mojo/public/cpp/bindings/tests/map_unittest.cc
index bb3c23d..698f407 100644
--- a/mojo/public/cpp/bindings/tests/map_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/map_unittest.cc
@@ -6,9 +6,9 @@
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/validate_params.h"
#include "mojo/public/cpp/bindings/map.h"
#include "mojo/public/cpp/bindings/string.h"
-#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/bindings/tests/container_test_util.h"
#include "mojo/public/cpp/environment/environment.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,6 +18,13 @@ namespace test {
namespace {
+using mojo::internal::Array_Data;
+using mojo::internal::ArrayValidateParams;
+using mojo::internal::FixedBuffer;
+using mojo::internal::Map_Data;
+using mojo::internal::NoValidateParams;
+using mojo::internal::String_Data;
+
struct StringIntData {
const char* string_data;
int int_data;
@@ -268,140 +275,52 @@ TEST_F(MapTest, MapArrayClone) {
}
}
-// Data class for an end-to-end test of serialization. Because making a more
-// limited test case tickles a clang compiler bug, we copy a minimal version of
-// what our current cpp bindings do.
-namespace internal {
-
-class ArrayOfMap_Data {
- public:
- static ArrayOfMap_Data* New(mojo::internal::Buffer* buf) {
- return new (buf->Allocate(sizeof(ArrayOfMap_Data))) ArrayOfMap_Data();
- }
-
- mojo::internal::StructHeader header_;
-
- mojo::internal::ArrayPointer<mojo::internal::Map_Data<int32_t, int8_t>*>
- first;
- mojo::internal::ArrayPointer<
- mojo::internal::Map_Data<mojo::internal::String_Data*,
- mojo::internal::Array_Data<bool>*>*> second;
-
- private:
- ArrayOfMap_Data() {
- header_.num_bytes = sizeof(*this);
- header_.num_fields = 2;
- }
- ~ArrayOfMap_Data(); // NOT IMPLEMENTED
-};
-static_assert(sizeof(ArrayOfMap_Data) == 24, "Bad sizeof(ArrayOfMap_Data)");
-
-} // namespace internal
-
-class ArrayOfMapImpl;
-typedef mojo::StructPtr<ArrayOfMapImpl> ArrayOfMapImplPtr;
-
-class ArrayOfMapImpl {
- public:
- typedef internal::ArrayOfMap_Data Data_;
- static ArrayOfMapImplPtr New() {
- ArrayOfMapImplPtr rv;
- mojo::internal::StructHelper<ArrayOfMapImpl>::Initialize(&rv);
- return rv.Pass();
- }
-
- mojo::Array<mojo::Map<int32_t, int8_t>> first;
- mojo::Array<mojo::Map<mojo::String, mojo::Array<bool>>> second;
-};
-
-size_t GetSerializedSize_(const ArrayOfMapImplPtr& input) {
- if (!input)
- return 0;
- size_t size = sizeof(internal::ArrayOfMap_Data);
- size += GetSerializedSize_(input->first);
- size += GetSerializedSize_(input->second);
- return size;
-}
-
-void Serialize_(ArrayOfMapImplPtr input,
- mojo::internal::Buffer* buf,
- internal::ArrayOfMap_Data** output) {
- if (input) {
- internal::ArrayOfMap_Data* result = internal::ArrayOfMap_Data::New(buf);
- mojo::SerializeArray_<mojo::internal::ArrayValidateParams<
- 0,
- false,
- mojo::internal::
- ArrayValidateParams<0, false, mojo::internal::NoValidateParams>>>(
- mojo::internal::Forward(input->first), buf, &result->first.ptr);
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !result->first.ptr,
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null first field in ArrayOfMapImpl struct");
- mojo::SerializeArray_<mojo::internal::ArrayValidateParams<
- 0,
- false,
- mojo::internal::ArrayValidateParams<
- 0,
- false,
- mojo::internal::ArrayValidateParams<
- 0,
- false,
- mojo::internal::NoValidateParams>>>>(
- mojo::internal::Forward(input->second), buf, &result->second.ptr);
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !result->second.ptr,
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null second field in ArrayOfMapImpl struct");
- *output = result;
- } else {
- *output = nullptr;
+TEST_F(MapTest, ArrayOfMap) {
+ {
+ Array<Map<int32_t, int8_t>> array(1);
+ array[0].insert(1, 42);
+
+ size_t size = GetSerializedSize_(array);
+ FixedBuffer buf(size);
+ Array_Data<Map_Data<int32_t, int8_t>*>* data;
+ SerializeArray_<ArrayValidateParams<
+ 0, false, ArrayValidateParams<0, false, NoValidateParams>>>(
+ array.Pass(), &buf, &data);
+
+ Array<Map<int32_t, int8_t>> deserialized_array;
+ Deserialize_(data, &deserialized_array);
+
+ ASSERT_EQ(1u, deserialized_array.size());
+ ASSERT_EQ(1u, deserialized_array[0].size());
+ ASSERT_EQ(42, deserialized_array[0].at(1));
}
-}
-void Deserialize_(internal::ArrayOfMap_Data* input, ArrayOfMapImplPtr* output) {
- if (input) {
- ArrayOfMapImplPtr result(ArrayOfMapImpl::New());
- Deserialize_(input->first.ptr, &result->first);
- Deserialize_(input->second.ptr, &result->second);
- *output = result.Pass();
- } else {
- output->reset();
+ {
+ Array<Map<String, Array<bool>>> array(1);
+ Array<bool> map_value(2);
+ map_value[0] = false;
+ map_value[1] = true;
+ array[0].insert("hello world", map_value.Pass());
+
+ size_t size = GetSerializedSize_(array);
+ FixedBuffer buf(size);
+ Array_Data<Map_Data<String_Data*, Array_Data<bool>*>*>* data;
+ SerializeArray_<ArrayValidateParams<
+ 0, false,
+ ArrayValidateParams<0, false,
+ ArrayValidateParams<0, false, NoValidateParams>>>>(
+ array.Pass(), &buf, &data);
+
+ Array<Map<String, Array<bool>>> deserialized_array;
+ Deserialize_(data, &deserialized_array);
+
+ ASSERT_EQ(1u, deserialized_array.size());
+ ASSERT_EQ(1u, deserialized_array[0].size());
+ ASSERT_FALSE(deserialized_array[0].at("hello world")[0]);
+ ASSERT_TRUE(deserialized_array[0].at("hello world")[1]);
}
}
-TEST_F(MapTest, ArrayOfMap) {
- Array<Map<int32_t, int8_t>> first_array(1);
- first_array[0].insert(1, 42);
-
- Array<Map<String, Array<bool>>> second_array(1);
- Array<bool> map_value(2);
- map_value[0] = false;
- map_value[1] = true;
- second_array[0].insert("hello world", map_value.Pass());
-
- ArrayOfMapImplPtr to_pass(ArrayOfMapImpl::New());
- to_pass->first = first_array.Pass();
- to_pass->second = second_array.Pass();
-
- size_t size = GetSerializedSize_(to_pass);
- mojo::internal::FixedBuffer buf(size);
- internal::ArrayOfMap_Data* data;
- Serialize_(mojo::internal::Forward(to_pass), &buf, &data);
-
- ArrayOfMapImplPtr to_receive(ArrayOfMapImpl::New());
- Deserialize_(data, &to_receive);
-
- ASSERT_EQ(1u, to_receive->first.size());
- ASSERT_EQ(1u, to_receive->first[0].size());
- ASSERT_EQ(42, to_receive->first[0].at(1));
-
- ASSERT_EQ(1u, to_receive->second.size());
- ASSERT_EQ(1u, to_receive->second[0].size());
- ASSERT_FALSE(to_receive->second[0].at("hello world")[0]);
- ASSERT_TRUE(to_receive->second[0].at("hello world")[1]);
-}
-
} // namespace
} // namespace test
} // namespace mojo
diff --git a/mojo/public/cpp/system/tests/macros_unittest.cc b/mojo/public/cpp/system/tests/macros_unittest.cc
index f884baa..89dd764 100644
--- a/mojo/public/cpp/system/tests/macros_unittest.cc
+++ b/mojo/public/cpp/system/tests/macros_unittest.cc
@@ -67,6 +67,8 @@ static_assert(MOJO_ARRAYSIZE(kGlobalArray) == 5u,
TEST(MacrosCppTest, ArraySize) {
double local_array[4] = {6.7, 7.8, 8.9, 9.0};
+ // MSVS considers this local variable unused since MOJO_ARRAYSIZE only takes
+ // the size of the type of the local and not the values itself.
MOJO_ALLOW_UNUSED_LOCAL(local_array);
EXPECT_EQ(4u, MOJO_ARRAYSIZE(local_array));
}
diff --git a/mojo/public/cpp/utility/lib/run_loop.cc b/mojo/public/cpp/utility/lib/run_loop.cc
index 5e01a63..9707e7e 100644
--- a/mojo/public/cpp/utility/lib/run_loop.cc
+++ b/mojo/public/cpp/utility/lib/run_loop.cc
@@ -219,7 +219,7 @@ bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) {
handler->OnHandleError(wait_state.handles[i], result);
return true;
}
- assert(MOJO_RESULT_DEADLINE_EXCEEDED == result);
+ assert(MOJO_RESULT_DEADLINE_EXCEEDED == result || MOJO_RESULT_OK == result);
}
return false;
}
diff --git a/mojo/public/dart/BUILD.gn b/mojo/public/dart/BUILD.gn
index 89af889..0acb310 100644
--- a/mojo/public/dart/BUILD.gn
+++ b/mojo/public/dart/BUILD.gn
@@ -54,10 +54,12 @@ copy("bindings") {
"core.dart",
"mojo_init.dart",
"src/buffer.dart",
+ "src/client.dart",
"src/codec.dart",
"src/data_pipe.dart",
"src/handle.dart",
"src/handle_watcher.dart",
+ "src/interface.dart",
"src/message_pipe.dart",
"src/types.dart",
]
diff --git a/mojo/public/dart/bindings.dart b/mojo/public/dart/bindings.dart
index 6a3be5f..1ae9697 100644
--- a/mojo/public/dart/bindings.dart
+++ b/mojo/public/dart/bindings.dart
@@ -4,10 +4,13 @@
library bindings;
+import 'core.dart' as core;
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:mirrors';
import 'dart:typed_data';
+part 'src/client.dart';
part 'src/codec.dart';
+part 'src/interface.dart';
diff --git a/mojo/public/dart/mojo_init.dart b/mojo/public/dart/mojo_init.dart
index 2b93af6..2a1cd6d 100644
--- a/mojo/public/dart/mojo_init.dart
+++ b/mojo/public/dart/mojo_init.dart
@@ -17,3 +17,7 @@ Future<Isolate> mojoInit() {
_mojoSystemThunksMake(core.mojoSystemThunksSet);
return core.MojoHandleWatcher.Start();
}
+
+void mojoShutdown() {
+ core.MojoHandleWatcher.Stop();
+}
diff --git a/mojo/public/dart/src/client.dart b/mojo/public/dart/src/client.dart
new file mode 100644
index 0000000..274fa47
--- /dev/null
+++ b/mojo/public/dart/src/client.dart
@@ -0,0 +1,103 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+part of bindings;
+
+abstract class Client {
+ core.MojoMessagePipeEndpoint _endpoint;
+ core.MojoHandle _handle;
+ List _sendQueue;
+ List _completerQueue;
+ bool _isOpen = false;
+
+ void handleResponse(MessageReader reader);
+
+ Client(this._endpoint) {
+ _sendQueue = [];
+ _completerQueue = [];
+ _handle = new core.MojoHandle(_endpoint.handle);
+ }
+
+ void open() {
+ _handle.listen((int mojoSignal) {
+ if (core.MojoHandleSignals.isReadable(mojoSignal)) {
+ // Query how many bytes are available.
+ var result = _endpoint.query();
+ if (!result.status.isOk && !result.status.isResourceExhausted) {
+ // If something else happens, it means the handle wasn't really ready
+ // for reading, which indicates a bug in MojoHandle or the
+ // handle watcher.
+ throw new Exception("message pipe query failed: ${result.status}");
+ }
+
+ // Read the data.
+ var bytes = new ByteData(result.bytesRead);
+ var handles = new List<core.RawMojoHandle>(result.handlesRead);
+ result = _endpoint.read(bytes, result.bytesRead, handles);
+ if (!result.status.isOk && !result.status.isResourceExhausted) {
+ throw new Exception("message pipe read failed: ${result.status}");
+ }
+ var message = new Message(bytes, handles);
+ var reader = new MessageReader(message);
+
+ handleResponse(reader);
+ }
+ if (core.MojoHandleSignals.isWritable(mojoSignal)) {
+ if (_sendQueue.length > 0) {
+ List messageCompleter = _sendQueue.removeAt(0);
+ _endpoint.write(messageCompleter[0].buffer);
+ if (!_endpoint.status.isOk) {
+ throw new Exception("message pipe write failed");
+ }
+ if (messageCompleter[1] != null) {
+ _completerQueue.add(messageCompleter[1]);
+ }
+ }
+ if ((_sendQueue.length == 0) && _handle.writeEnabled()) {
+ _handle.disableWriteEvents();
+ }
+ }
+ if (core.MojoHandleSignals.isNone(mojoSignal)) {
+ // The handle watcher will send MojoHandleSignals.NONE if the other
+ // endpoint of the pipe is closed.
+ _handle.close();
+ }
+ });
+ _isOpen = true;
+ }
+
+ void close() {
+ assert(isOpen);
+ _handle.close();
+ _isOpen = false;
+ }
+
+ void enqueueMessage(Type t, int name, Object msg) {
+ var builder = new MessageBuilder(name, align(getEncodedSize(t)));
+ builder.encodeStruct(t, msg);
+ var message = builder.finish();
+ _sendQueue.add([message, null]);
+ if ((_sendQueue.length > 0) && !_handle.writeEnabled()) {
+ _handle.enableWriteEvents();
+ }
+ }
+
+ Future enqueueMessageWithRequestID(Type t, int name, int id, Object msg) {
+ var builder = new MessageWithRequestIDBuilder(
+ name, align(getEncodedSize(t)), id);
+ builder.encodeStruct(t, msg);
+ var message = builder.finish();
+
+ var completer = new Completer();
+ _sendQueue.add([message, completer]);
+ if ((_sendQueue.length > 0) && !_handle.writeEnabled()) {
+ _handle.enableWriteEvents();
+ }
+ return completer.future;
+ }
+
+ // Need a getter for this for access in subclasses.
+ List get completerQueue => _completerQueue;
+ bool get isOpen => _isOpen;
+}
diff --git a/mojo/public/dart/src/codec.dart b/mojo/public/dart/src/codec.dart
index 003fcc1..286df12 100644
--- a/mojo/public/dart/src/codec.dart
+++ b/mojo/public/dart/src/codec.dart
@@ -66,7 +66,7 @@ int getEncodedSize(Object typeOrInstance) {
class MojoDecoder {
ByteData buffer;
- List<int> handles;
+ List<core.RawMojoHandle> handles;
int base;
int next;
@@ -151,7 +151,7 @@ class MojoDecoder {
return new MojoDecoder(buffer, handles, offset);
}
- int decodeHandle() {
+ core.RawMojoHandle decodeHandle() {
return handles[readUint32()];
}
@@ -234,7 +234,7 @@ class MojoDecoder {
class MojoEncoder {
ByteData buffer;
- List<int> handles;
+ List<core.RawMojoHandle> handles;
int base;
int next;
int extent;
@@ -341,7 +341,7 @@ class MojoEncoder {
return new MojoEncoder(buffer, handles, pointer, extent);
}
- void encodeHandle(int handle) {
+ void encodeHandle(core.RawMojoHandle handle) {
handles.add(handle);
writeUint32(handles.length - 1);
}
@@ -456,7 +456,7 @@ const int kMessageIsResponse = 1 << 1;
class Message {
ByteData buffer;
- List<int> handles;
+ List<core.RawMojoHandle> handles;
Message(this.buffer, this.handles);
@@ -475,12 +475,14 @@ class Message {
class MessageBuilder {
MojoEncoder encoder;
- List<int> handles;
+ List<core.RawMojoHandle> handles;
+
+ MessageBuilder._();
MessageBuilder(int name, int payloadSize) {
int numBytes = kMessageHeaderSize + payloadSize;
var buffer = new ByteData(numBytes);
- handles = [];
+ handles = <core.RawMojoHandle>[];
encoder = new MojoEncoder(buffer, handles, 0, kMessageHeaderSize);
encoder.writeUint32(kMessageHeaderSize);
@@ -517,20 +519,19 @@ class MessageBuilder {
class MessageWithRequestIDBuilder extends MessageBuilder {
MessageWithRequestIDBuilder(
- int name, int payloadSize, int flags, int requestID) {
+ int name, int payloadSize, int requestID, [int flags = 0])
+ : super._() {
int numBytes = kMessageWithRequestIDHeaderSize + payloadSize;
- buffer = new ByteData(numBytes);
- handles = [];
- base = 0;
+ var buffer = new ByteData(numBytes);
+ handles = <core.RawMojoHandle>[];
- encoder = createEncoder(0, kMessageWithRequestIDHeaderSize);
+ encoder = new MojoEncoder(
+ buffer, handles, 0, kMessageWithRequestIDHeaderSize);
encoder.writeUint32(kMessageWithRequestIDHeaderSize);
encoder.writeUint32(3); // num_fields.
encoder.writeUint32(name);
encoder.writeUint32(flags);
encoder.writeUint64(requestID);
- base = encoder.next;
- buffer = encoder.buffer;
}
}
@@ -564,7 +565,7 @@ class MessageReader {
abstract class MojoType<T> {
static const int encodedSize = 0;
- static T decode(MojoDecoder decoder) { return null }
+ static T decode(MojoDecoder decoder) { return null; }
static void encode(MojoEncoder encoder, T val) {}
}
@@ -704,7 +705,7 @@ class PointerTo {
class NullablePointerTo extends PointerTo {
- static const int encodedSize = PointerTo.encodedSize;
+ NullablePointerTo(Object val) : super(val);
}
@@ -725,14 +726,14 @@ class ArrayOf {
class NullableArrayOf extends ArrayOf {
- static const int encodedSize = ArrayOf.encodedSize;
+ NullableArrayOf(Object val, [int length = 0]) : super(val, length);
}
-class Handle implements MojoType<int> {
+class Handle implements MojoType<core.RawMojoHandle> {
static const int encodedSize = 4;
- static int decode(MojoDecoder decoder) => decoder.decodeHandle();
- static void encode(MojoEncoder encoder, int val) {
+ static core.RawMojoHandle decode(MojoDecoder decoder) => decoder.decodeHandle();
+ static void encode(MojoEncoder encoder, core.RawMojoHandle val) {
encoder.encodeHandle(val);
}
}
diff --git a/mojo/public/dart/src/handle.dart b/mojo/public/dart/src/handle.dart
index bf9d87b..bf2f74e 100644
--- a/mojo/public/dart/src/handle.dart
+++ b/mojo/public/dart/src/handle.dart
@@ -5,6 +5,7 @@
part of core;
class _MojoHandleNatives {
+ static int register(MojoHandle handle) native "MojoHandle_Register";
static int close(int handle) native "MojoHandle_Close";
static int wait(int handle, int signals, int deadline)
native "MojoHandle_Wait";
@@ -62,9 +63,17 @@ class RawMojoHandle {
handles, signals, handles.length, deadline);
}
- static bool isValid(RawMojoHandle h) => (h.h != INVALID);
+ static MojoResult register(MojoHandle handle) {
+ return new MojoResult(_MojoHandleNatives.register(handle));
+ }
+
+ bool get isValid => (h != INVALID);
String toString() => "$h";
+
+ bool operator ==(RawMojoHandle other) {
+ return h == other.h;
+ }
}
@@ -92,25 +101,24 @@ class MojoHandle extends Stream<int> {
MojoHandle(this._handle) :
_signals = MojoHandleSignals.READABLE,
- _eventHandlerAdded = false,
- _receivePort = new ReceivePort() {
- _sendPort = _receivePort.sendPort;
- _controller = new StreamController(sync: true,
- onListen: _onSubscriptionStateChange,
- onCancel: _onSubscriptionStateChange,
- onPause: _onPauseStateChange,
- onResume: _onPauseStateChange);
- _controller.addStream(_receivePort);
+ _eventHandlerAdded = false {
+ MojoResult result = RawMojoHandle.register(this);
+ if (!result.isOk) {
+ throw new Exception("Failed to register the MojoHandle");
+ }
}
void close() {
if (_eventHandlerAdded) {
MojoHandleWatcher.close(_handle);
+ _eventHandlerAdded = false;
} else {
// If we're not in the handle watcher, then close the handle manually.
_handle.close();
}
- _receivePort.close();
+ if (_receivePort != null) {
+ _receivePort.close();
+ }
}
// We wrap the callback provided by clients in listen() with some code to
@@ -125,11 +133,11 @@ class MojoHandle extends Stream<int> {
// The callback could have closed the handle. If so, don't add it back to
// the MojoHandleWatcher.
- if (RawMojoHandle.isValid(_handle)) {
+ if (_handle.isValid) {
assert(!_eventHandlerAdded);
var res = MojoHandleWatcher.add(_handle, _sendPort, _signals);
if (!res.isOk) {
- throw new Exception("Failed to re-add handle: $_handle");
+ throw new Exception("Failed to re-add handle: $res");
}
_eventHandlerAdded = true;
}
@@ -139,6 +147,14 @@ class MojoHandle extends Stream<int> {
StreamSubscription<int> listen(
void onData(int event),
{Function onError, void onDone(), bool cancelOnError}) {
+ _receivePort = new ReceivePort();
+ _sendPort = _receivePort.sendPort;
+ _controller = new StreamController(sync: true,
+ onListen: _onSubscriptionStateChange,
+ onCancel: _onSubscriptionStateChange,
+ onPause: _onPauseStateChange,
+ onResume: _onPauseStateChange);
+ _controller.addStream(_receivePort);
assert(!_eventHandlerAdded);
var res = MojoHandleWatcher.add(_handle, _sendPort, _signals);
@@ -185,7 +201,10 @@ class MojoHandle extends Stream<int> {
void _onPauseStateChange() {
if (_controller.isPaused) {
if (_eventHandlerAdded) {
- MojoHandleWatcher.remove(_handle);
+ var res = MojoHandleWatcher.remove(_handle);
+ if (!res.isOk) {
+ throw new Exception("MojoHandleWatcher add failed: $res");
+ }
_eventHandlerAdded = false;
}
} else {
diff --git a/mojo/public/dart/src/handle_watcher.dart b/mojo/public/dart/src/handle_watcher.dart
index 47f3675..5f05654 100644
--- a/mojo/public/dart/src/handle_watcher.dart
+++ b/mojo/public/dart/src/handle_watcher.dart
@@ -103,12 +103,6 @@ class MojoHandleWatcher {
watcher._routeEvent(res);
// Remove the handle from the list.
watcher._removeHandle(handle);
- } else if (res == MojoResult.kFailedPrecondition) {
- // None of the handles can ever be satisfied, including the control
- // handle. This probably means we are going down. Clean up and
- // shutdown.
- watcher._pruneClosedHandles();
- watcher._shutdown = true;
} else {
// Some handle was closed, but not by us.
// We have to go through the list and find it.
@@ -159,7 +153,7 @@ class MojoHandleWatcher {
_close(result[0]);
break;
case SHUTDOWN:
- _shutdown = true;
+ _shutdownHandleWatcher();
break;
default:
throw new Exception("Invalid Command: $command");
@@ -204,7 +198,7 @@ class MojoHandleWatcher {
}
}
- void _close(int mojoHandle) {
+ void _close(int mojoHandle, {bool pruning : false}) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
throw new Exception("Close on a non-existent handle: idx = $idx.");
@@ -215,13 +209,19 @@ class MojoHandleWatcher {
_tempHandle.h = _handles[idx];
_tempHandle.close();
_tempHandle.h = RawMojoHandle.INVALID;
+ if (pruning) {
+ // If this handle is being pruned, notify the application isolate
+ // by sending MojoHandleSignals.NONE.
+ _ports[idx].send(MojoHandleSignals.NONE);
+ }
_removeHandle(mojoHandle);
}
void _toggleWrite(int mojoHandle) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
- throw new Exception("Toggle write on a non-existent handle: idx = $idx.");
+ throw new Exception(
+ "Toggle write on a non-existent handle: $mojoHandle.");
}
if (idx == 0) {
throw new Exception("The control handle (idx = 0) cannot be toggled.");
@@ -240,10 +240,17 @@ class MojoHandleWatcher {
_tempHandle.h = RawMojoHandle.INVALID;
}
for (var h in closed) {
- _close(h);
+ _close(h, pruning: true);
}
}
+ void _shutdownHandleWatcher() {
+ _shutdown = true;
+ _tempHandle.h = _controlHandle;
+ _tempHandle.close();
+ _tempHandle.h = RawMojoHandle.INVALID;
+ }
+
static MojoResult _sendControlData(RawMojoHandle mojoHandle,
SendPort port,
int data) {
@@ -251,14 +258,17 @@ class MojoHandleWatcher {
if (controlHandle == RawMojoHandle.INVALID) {
throw new Exception("Found invalid control handle");
}
+
+ int rawHandle = RawMojoHandle.INVALID;
+ if (mojoHandle != null) {
+ rawHandle = mojoHandle.h;
+ }
var result = _MojoHandleWatcherNatives.sendControlData(
- controlHandle, mojoHandle.h, port, data);
+ controlHandle, rawHandle, port, data);
return new MojoResult(result);
}
static Future<Isolate> Start() {
- // 5. Return Future<bool> giving true on success.
-
// Make a control message pipe,
MojoMessagePipe pipe = new MojoMessagePipe();
int consumerHandle = pipe.endpoints[0].handle.h;
@@ -275,7 +285,13 @@ class MojoHandleWatcher {
}
static void Stop() {
- _sendControlData(RawMojoHandle.INVALID, null, _encodeCommand(SHUTDOWN));
+ // Send the shutdown command.
+ _sendControlData(null, null, _encodeCommand(SHUTDOWN));
+
+ // Close the control handle.
+ int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
+ var handle = new RawMojoHandle(controlHandle);
+ handle.close();
}
static MojoResult close(RawMojoHandle mojoHandle) {
diff --git a/mojo/public/dart/src/interface.dart b/mojo/public/dart/src/interface.dart
new file mode 100644
index 0000000..298ab72
--- /dev/null
+++ b/mojo/public/dart/src/interface.dart
@@ -0,0 +1,86 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+part of bindings;
+
+abstract class Interface {
+ core.MojoMessagePipeEndpoint _endpoint;
+ core.MojoHandle _handle;
+ List _sendQueue;
+
+ Message handleMessage(MessageReader reader, Function messageHandler);
+
+ Interface(this._endpoint) {
+ _sendQueue = [];
+ _handle = new core.MojoHandle(_endpoint.handle);
+ }
+
+ StreamSubscription<int> listen(Function messageHandler) {
+ return _handle.listen((int mojoSignal) {
+ if (core.MojoHandleSignals.isReadable(mojoSignal)) {
+ // Query how many bytes are available.
+ var result = _endpoint.query();
+ if (!result.status.isOk && !result.status.isResourceExhausted) {
+ // If something else happens, it means the handle wasn't really ready
+ // for reading, which indicates a bug in MojoHandle or the
+ // event listener.
+ throw new Exception("message pipe query failed: ${result.status}");
+ }
+
+ // Read the data and view as a message.
+ var bytes = new ByteData(result.bytesRead);
+ var handles = new List<RawMojoHandle>(result.handlesRead);
+ result = _endpoint.read(bytes, result.bytesRead, handles);
+ if (!result.status.isOk && !result.status.isResourceExhausted) {
+ // If something else happens, it means the handle wasn't really ready
+ // for reading, which indicates a bug in MojoHandle or the
+ // event listener.
+ throw new Exception("message pipe read failed: ${result.status}");
+ }
+ var message = new Message(bytes, handles);
+ var reader = new MessageReader(message);
+
+ // Prepare the response.
+ var response_message = handleMessage(reader, messageHandler);
+ // If there's a response, queue it up for sending.
+ if (response_message != null) {
+ _sendQueue.add(response_message);
+ if ((_sendQueue.length > 0) && !_handle.writeEnabled()) {
+ _handle.enableWriteEvents();
+ }
+ }
+ }
+ if (core.MojoHandleSignals.isWritable(mojoSignal)) {
+ if (_sendQueue.length > 0) {
+ var response_message = _sendQueue.removeAt(0);
+ _endpoint.write(response_message.buffer);
+ if (!_endpoint.status.isOk) {
+ throw new Exception("message pipe write failed");
+ }
+ }
+ if ((_sendQueue.length == 0) && _handle.writeEnabled()) {
+ _handle.disableWriteEvents();
+ }
+ }
+ if (core.MojoHandleSignals.isNone(mojoSignal)) {
+ // The handle watcher will send MojoHandleSignals.NONE when the other
+ // endpoint of the pipe is closed.
+ _handle.close();
+ }
+ });
+ }
+
+ Message buildResponse(Type t, int name, Object response) {
+ var builder = new MessageBuilder(name, align(getEncodedSize(t)));
+ builder.encodeStruct(t, response);
+ return builder.finish();
+ }
+
+ Message buildResponseWithID(Type t, int name, int id, Object response) {
+ var builder = new MessageWithRequestIDBuilder(
+ name, align(getEncodedSize(t)), id);
+ builder.encodeStruct(t, response);
+ return builder.finish();
+ }
+}
diff --git a/mojo/public/dart/src/mojo_dart_core.cc b/mojo/public/dart/src/mojo_dart_core.cc
index 12e5858..27b2e3f 100644
--- a/mojo/public/dart/src/mojo_dart_core.cc
+++ b/mojo/public/dart/src/mojo_dart_core.cc
@@ -76,6 +76,73 @@ static void MojoSystemThunks_Set(Dart_NativeArguments arguments) {
}
+struct CloserCallbackPeer {
+ MojoHandle handle;
+};
+
+
+static void MojoHandleCloserCallback(void* isolate_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {
+ CloserCallbackPeer* callback_peer =
+ reinterpret_cast<CloserCallbackPeer*>(peer);
+ if (callback_peer->handle != MOJO_HANDLE_INVALID) {
+ MojoClose(callback_peer->handle);
+ }
+ delete callback_peer;
+}
+
+
+// Setup a weak persistent handle for a Dart MojoHandle that calls MojoClose
+// on the handle when the MojoHandle is GC'd or the VM is going down.
+static void MojoHandle_Register(Dart_NativeArguments arguments) {
+ // An instance of Dart class MojoHandle.
+ Dart_Handle mojo_handle_instance = Dart_GetNativeArgument(arguments, 0);
+ if (!Dart_IsInstance(mojo_handle_instance)) {
+ SetInvalidArgumentReturn(arguments);
+ return;
+ }
+ // TODO(zra): Here, we could check that mojo_handle_instance is really a
+ // MojoHandle instance, but with the Dart API it's not too easy to get a Type
+ // object from the class name outside of the root library. For now, we'll rely
+ // on the existence of the right fields to be sufficient.
+
+ Dart_Handle raw_mojo_handle_instance = Dart_GetField(
+ mojo_handle_instance, Dart_NewStringFromCString("_handle"));
+ if (Dart_IsError(raw_mojo_handle_instance)) {
+ SetInvalidArgumentReturn(arguments);
+ return;
+ }
+
+ Dart_Handle mojo_handle = Dart_GetField(
+ raw_mojo_handle_instance, Dart_NewStringFromCString("h"));
+ if (Dart_IsError(mojo_handle)) {
+ SetInvalidArgumentReturn(arguments);
+ return;
+ }
+
+ int64_t raw_handle = static_cast<int64_t>(MOJO_HANDLE_INVALID);
+ Dart_Handle result = Dart_IntegerToInt64(mojo_handle, &raw_handle);
+ if (Dart_IsError(result)) {
+ SetInvalidArgumentReturn(arguments);
+ return;
+ }
+
+ if (raw_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) {
+ SetInvalidArgumentReturn(arguments);
+ return;
+ }
+
+ CloserCallbackPeer* callback_peer = new CloserCallbackPeer();
+ callback_peer->handle = static_cast<MojoHandle>(raw_handle);
+ Dart_NewWeakPersistentHandle(mojo_handle_instance,
+ reinterpret_cast<void*>(callback_peer),
+ sizeof(CloserCallbackPeer),
+ MojoHandleCloserCallback);
+ Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK));
+}
+
+
static void MojoHandle_Close(Dart_NativeArguments arguments) {
int64_t handle;
CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument);
@@ -613,8 +680,7 @@ static void MojoHandleWatcher_SendControlData(Dart_NativeArguments arguments) {
cd.data = data;
const void* bytes = reinterpret_cast<const void*>(&cd);
MojoResult res = MojoWriteMessage(
- control_handle, bytes, sizeof(cd), NULL, 0, 0);
-
+ control_handle, bytes, sizeof(cd), NULL, 0, 0);
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res));
}
@@ -647,7 +713,7 @@ static void MojoHandleWatcher_SetControlHandle(Dart_NativeArguments arguments) {
int64_t control_handle;
CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument);
- if (mojo_control_handle == MOJO_HANDLE_INVALID) {
+ if (mojo_control_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) {
mojo_control_handle = control_handle;
}
@@ -674,6 +740,7 @@ static void MojoHandleWatcher_GetControlHandle(Dart_NativeArguments arguments) {
V(MojoMessagePipe_Create) \
V(MojoMessagePipe_Write) \
V(MojoMessagePipe_Read) \
+ V(MojoHandle_Register) \
V(MojoHandle_WaitMany) \
V(MojoHandleWatcher_SendControlData) \
V(MojoHandleWatcher_RecvControlData) \
diff --git a/mojo/public/dart/src/types.dart b/mojo/public/dart/src/types.dart
index 658e477..4353d74 100644
--- a/mojo/public/dart/src/types.dart
+++ b/mojo/public/dart/src/types.dart
@@ -91,6 +91,30 @@ class MojoResult {
bool get isDataLoss => (this == DATA_LOSS);
bool get isBusy => (this == BUSY);
bool get isShouldWait => (this == SHOULD_WAIT);
+
+ String toString() {
+ switch (value) {
+ case kOk: return "OK";
+ case kCancelled: return "CANCELLED";
+ case kUnknown: return "UNKNOWN";
+ case kInvalidArgument: return "INVALID_ARGUMENT";
+ case kDeadlineExceeded: return "DEADLINE_EXCEEDED";
+ case kNotFound: return "NOT_FOUND";
+ case kAlreadyExists: return "ALREADY_EXISTS";
+ case kPermissionDenied: return "PERMISSION_DENIED";
+ case kResourceExhausted: return "RESOURCE_EXHAUSTED";
+ case kFailedPrecondition: return "FAILED_PRECONDITION";
+ case kAborted: return "ABORTED";
+ case kOutOfRange: return "OUT_OF_RANGE";
+ case kUnimplemented: return "UNIMPLEMENTED";
+ case kInternal: return "INTERNAL";
+ case kUnavailable: return "UNAVAILABLE";
+ case kDataLoss: return "DATA_LOSS";
+ case kBusy: return "BUSY";
+ case kShouldWait: return "SHOULD_WAIT";
+ default: return "<invalid result>";
+ }
+ }
}
@@ -100,6 +124,7 @@ class MojoHandleSignals {
static const int WRITABLE = 1 << 1;
static const int READWRITE = READABLE | WRITABLE;
+ static bool isNone(int mask) => mask == NONE;
static bool isReadable(int mask) => (mask & READABLE) == READABLE;
static bool isWritable(int mask) => (mask & WRITABLE) == WRITABLE;
static bool isReadWrite(int mask) => (mask & READWRITE) == READWRITE;
diff --git a/mojo/public/interfaces/bindings/tests/test_structs.mojom b/mojo/public/interfaces/bindings/tests/test_structs.mojom
index b525a2f..87ada07 100644
--- a/mojo/public/interfaces/bindings/tests/test_structs.mojom
+++ b/mojo/public/interfaces/bindings/tests/test_structs.mojom
@@ -136,4 +136,9 @@ struct MapValueTypes {
map<string, array<string, 2>> f3;
map<string, array<array<string, 2>?>> f4;
map<string, array<array<string, 2>, 1>> f5;
+ map<string, Rect?> f6;
+ // TODO(hansmuller, yzshen): Uncomment these once the JavaScript bindings
+ // generator is fixed.
+ // map<string, map<string, string>> f7;
+ // map<string, array<map<string, string>>> f8;
};
diff --git a/mojo/public/js/connection.js b/mojo/public/js/connection.js
index d9b64aa..748ca5c 100644
--- a/mojo/public/js/connection.js
+++ b/mojo/public/js/connection.js
@@ -4,21 +4,22 @@
define("mojo/public/js/connection", [
"mojo/public/js/connector",
+ "mojo/public/js/core",
"mojo/public/js/router",
-], function(connector, router) {
+], function(connector, core, routerModule) {
- function Connection(
- handle, localFactory, remoteFactory, routerFactory, connectorFactory) {
- if (routerFactory === undefined)
- routerFactory = router.Router;
- this.router_ = new routerFactory(handle, connectorFactory);
- this.remote = remoteFactory && new remoteFactory(this.router_);
- this.local = localFactory && new localFactory(this.remote);
- this.router_.setIncomingReceiver(this.local);
+ function BaseConnection(localStub, remoteProxy, router) {
+ this.router_ = router;
+ this.local = localStub;
+ this.remote = remoteProxy;
+
+ this.router_.setIncomingReceiver(localStub);
+ if (this.remote)
+ this.remote.receiver_ = router;
// Validate incoming messages: remote responses and local requests.
- var validateRequest = localFactory && localFactory.prototype.validator;
- var validateResponse = remoteFactory.prototype.validator;
+ var validateRequest = localStub && localStub.validator;
+ var validateResponse = remoteProxy && remoteProxy.validator;
var payloadValidators = [];
if (validateRequest)
payloadValidators.push(validateRequest);
@@ -27,17 +28,28 @@ define("mojo/public/js/connection", [
this.router_.setPayloadValidators(payloadValidators);
}
- Connection.prototype.close = function() {
+ BaseConnection.prototype.close = function() {
this.router_.close();
this.router_ = null;
this.local = null;
this.remote = null;
};
- Connection.prototype.encounteredError = function() {
+ BaseConnection.prototype.encounteredError = function() {
return this.router_.encounteredError();
};
+ function Connection(
+ handle, localFactory, remoteFactory, routerFactory, connectorFactory) {
+ var routerClass = routerFactory || routerModule.Router;
+ var router = new routerClass(handle, connectorFactory);
+ var remoteProxy = remoteFactory && new remoteFactory(router);
+ var localStub = localFactory && new localFactory(remoteProxy);
+ BaseConnection.call(this, localStub, remoteProxy, router);
+ }
+
+ Connection.prototype = Object.create(BaseConnection.prototype);
+
// The TestConnection subclass is only intended to be used in unit tests.
function TestConnection(handle, localFactory, remoteFactory) {
@@ -45,14 +57,42 @@ define("mojo/public/js/connection", [
handle,
localFactory,
remoteFactory,
- router.TestRouter,
+ routerModule.TestRouter,
connector.TestConnector);
}
TestConnection.prototype = Object.create(Connection.prototype);
+ function createOpenConnection(stub, proxy) {
+ var messagePipe = core.createMessagePipe();
+ // TODO(hansmuller): Check messagePipe.result.
+ var router = new routerModule.Router(messagePipe.handle0);
+ var connection = new BaseConnection(stub, proxy, router);
+ connection.messagePipeHandle = messagePipe.handle1;
+ return connection;
+ }
+
+ function getProxyConnection(proxy, proxyInterface) {
+ if (!proxy.connection_) {
+ var stub = proxyInterface.client && new proxyInterface.client.stubClass;
+ proxy.connection_ = createOpenConnection(stub, proxy);
+ }
+ return proxy.connection_;
+ }
+
+ function getStubConnection(stub, proxyInterface) {
+ if (!stub.connection_) {
+ var proxy = proxyInterface.client && new proxyInterface.client.proxyClass;
+ stub.connection_ = createOpenConnection(stub, proxy);
+ }
+ return stub.connection_;
+ }
+
+
var exports = {};
exports.Connection = Connection;
exports.TestConnection = TestConnection;
+ exports.getProxyConnection = getProxyConnection;
+ exports.getStubConnection = getStubConnection;
return exports;
});
diff --git a/mojo/public/js/struct_unittests.js b/mojo/public/js/struct_unittests.js
index 092d239..c72f8eb 100644
--- a/mojo/public/js/struct_unittests.js
+++ b/mojo/public/js/struct_unittests.js
@@ -143,12 +143,24 @@ define([
function testMapValueTypes() {
var mapFieldsStruct = new testStructs.MapValueTypes({
- f0: new Map([["a", ["b", "c"]], ["d", ["e"]]]), // array<string>>
- f1: new Map([["a", null], ["b", ["c", "d"]]]), // array<string>?>
- f2: new Map([["a", [null]], ["b", [null, "d"]]]), // array<string?>>
- f3: new Map([["a", ["1", "2"]], ["b", ["1", "2"]]]), // array<string,2>>
- f4: new Map([["a", [["1"]]], ["b", [null]]]), // array<array<string, 1>?>
- f5: new Map([["a", [["1", "2"]]]]), // array<array<string, 2>, 1>>
+ // array<string>>
+ f0: new Map([["a", ["b", "c"]], ["d", ["e"]]]),
+ // array<string>?>
+ f1: new Map([["a", null], ["b", ["c", "d"]]]),
+ // array<string?>>
+ f2: new Map([["a", [null]], ["b", [null, "d"]]]),
+ // array<string,2>>
+ f3: new Map([["a", ["1", "2"]], ["b", ["1", "2"]]]),
+ // array<array<string, 1>?>
+ f4: new Map([["a", [["1"]]], ["b", [null]]]),
+ // array<array<string, 2>, 1>>
+ f5: new Map([["a", [["1", "2"]]]]),
+ // map<string, Rect?>
+ f6: new Map([["a", null]]),
+ // map<string, map<string, string>>
+ // f7: new Map([["a", new Map([["b", "c"]])]]),
+ // map<string, array<map<string, string>>>
+ // f8: new Map([["a", [new Map([["b", "c"]])]]]),
});
var decodedStruct = structEncodeDecode(mapFieldsStruct);
expect(decodedStruct.f0).toEqual(mapFieldsStruct.f0);
@@ -157,6 +169,9 @@ define([
expect(decodedStruct.f3).toEqual(mapFieldsStruct.f3);
expect(decodedStruct.f4).toEqual(mapFieldsStruct.f4);
expect(decodedStruct.f5).toEqual(mapFieldsStruct.f5);
+ expect(decodedStruct.f6).toEqual(mapFieldsStruct.f6);
+ // expect(decodedStruct.f7).toEqual(mapFieldsStruct.f7);
+ // expect(decodedStruct.f8).toEqual(mapFieldsStruct.f8);
}
testConstructors();
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni
index b14adbf..83b96a2 100644
--- a/mojo/public/mojo_application.gni
+++ b/mojo/public/mojo_application.gni
@@ -88,7 +88,7 @@ template("mojo_native_application") {
check_includes = invoker.check_includes
}
if (defined(invoker.configs)) {
- configs = invoker.configs
+ configs += invoker.configs
}
if (defined(invoker.data)) {
data = invoker.data
diff --git a/mojo/public/python/mojo/bindings/reflection.py b/mojo/public/python/mojo/bindings/reflection.py
index 3193f6e3..5ca38bf 100644
--- a/mojo/public/python/mojo/bindings/reflection.py
+++ b/mojo/public/python/mojo/bindings/reflection.py
@@ -42,11 +42,11 @@ class MojoEnumType(type):
raise ValueError('incorrect value: %r' % value)
return type.__new__(mcs, name, bases, dictionary)
- def __setattr__(mcs, key, value):
- raise AttributeError, 'can\'t set attribute'
+ def __setattr__(cls, key, value):
+ raise AttributeError('can\'t set attribute')
- def __delattr__(mcs, key):
- raise AttributeError, 'can\'t delete attribute'
+ def __delattr__(cls, key):
+ raise AttributeError('can\'t delete attribute')
class MojoStructType(type):
@@ -131,12 +131,12 @@ class MojoStructType(type):
return type.__new__(mcs, name, bases, dictionary)
# Prevent adding new attributes, or mutating constants.
- def __setattr__(mcs, key, value):
- raise AttributeError, 'can\'t set attribute'
+ def __setattr__(cls, key, value):
+ raise AttributeError('can\'t set attribute')
# Prevent deleting constants.
- def __delattr__(mcs, key):
- raise AttributeError, 'can\'t delete attribute'
+ def __delattr__(cls, key):
+ raise AttributeError('can\'t delete attribute')
class MojoInterfaceType(type):
@@ -195,16 +195,16 @@ class MojoInterfaceType(type):
return interface_class
@property
- def manager(mcs):
- return mcs._interface_manager
+ def manager(cls):
+ return cls._interface_manager
# Prevent adding new attributes, or mutating constants.
- def __setattr__(mcs, key, value):
- raise AttributeError, 'can\'t set attribute'
+ def __setattr__(cls, key, value):
+ raise AttributeError('can\'t set attribute')
# Prevent deleting constants.
- def __delattr__(mcs, key):
- raise AttributeError, 'can\'t delete attribute'
+ def __delattr__(cls, key):
+ raise AttributeError('can\'t delete attribute')
class InterfaceProxy(object):
diff --git a/mojo/public/sky/convert_amd_modules_to_sky.py b/mojo/public/sky/convert_amd_modules_to_sky.py
index 8712784..4a7ed8d 100755
--- a/mojo/public/sky/convert_amd_modules_to_sky.py
+++ b/mojo/public/sky/convert_amd_modules_to_sky.py
@@ -70,15 +70,15 @@ def Parse(amd_module):
AddImportNames(module, m.group(1))
state = "body"
continue
- raise Exception, "Unknown import declaration:" + line
+ raise Exception("Unknown import declaration:" + line)
if state == "body":
if end_body_regexp.search(line):
module.body = "\n".join(body_lines)
return module
body_lines.append(line)
continue
- raise Exception, "Unknown parser state"
- raise Exception, "End of file reached with finding a module"
+ raise Exception("Unknown parser state")
+ raise Exception("End of file reached with finding a module")
def main():
parser = argparse.ArgumentParser()
diff --git a/mojo/public/tools/bindings/generators/dart_templates/enum_definition.tmpl b/mojo/public/tools/bindings/generators/dart_templates/enum_definition.tmpl
new file mode 100644
index 0000000..bfab117
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/dart_templates/enum_definition.tmpl
@@ -0,0 +1,12 @@
+{%- macro enum_def(prefix, enum) -%}
+{%- set prev_enum = 0 %}
+{%- for field in enum.fields %}
+{%- if field.value %}
+{{prefix}}final int {{enum.name}}_{{field.name}} = {{field.value|expression_to_text}};
+{%- elif loop.first %}
+{{prefix}}final int {{enum.name}}_{{field.name}} = 0;
+{%- else %}
+{{prefix}}final int {{enum.name}}_{{field.name}} = {{enum.fields[loop.index0 - 1].name}} + 1;
+{%- endif %}
+{%- endfor %}
+{%- endmacro %}
diff --git a/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
new file mode 100644
index 0000000..ddc1de8
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
@@ -0,0 +1,107 @@
+{%- for method in interface.methods %}
+const int k{{interface.name}}_{{method.name}}_name = {{method.ordinal}};
+{%- endfor %}
+
+
+class {{interface.name}}Client extends bindings.Client {
+ {{interface.name}}Client(core.MojoMessagePipeEndpoint endpoint) : super(endpoint);
+
+{%- for method in interface.methods %}
+{%- if method.response_parameters == None %}
+ void {{method.name|stylize_method}}(
+{%- for parameter in method.parameters -%}
+ {{parameter.kind|dart_decl_type}} {{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor -%}
+ ) {
+ assert(isOpen);
+ var params = new {{interface.name}}_{{method.name}}_Params();
+{%- for parameter in method.parameters %}
+ params.{{parameter.name}} = {{parameter.name}};
+{%- endfor %}
+ enqueueMessage({{interface.name}}_{{method.name}}_Params,
+ k{{interface.name}}_{{method.name}}_name,
+ params);
+ }
+{% else %}
+ Future<{{interface.name}}_{{method.name}}_ResponseParams> {{method.name|stylize_method}}(
+{%- for parameter in method.parameters -%}
+ {{parameter.kind|dart_decl_type}} {{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor -%}
+ ) {
+ assert(isOpen);
+ var params = new {{interface.name}}_{{method.name}}_Params();
+{%- for parameter in method.parameters %}
+ params.{{parameter.name}} = {{parameter.name}};
+{%- endfor %}
+ return enqueueMessageWithRequestID(
+ {{interface.name}}_{{method.name}}_Params,
+ k{{interface.name}}_{{method.name}}_name,
+ bindings.kMessageExpectsResponse,
+ params);
+ }
+{%- endif %}
+{%- endfor %}
+
+ void handleResponse(bindings.MessageReader reader) {
+ switch (reader.name) {
+{%- for method in interface.methods %}
+{%- if method.response_parameters != None %}
+ case k{{interface.name}}_{{method.name}}_name:
+ var r = reader.decodeStruct({{interface.name}}_{{method.name}}_ResponseParams);
+ Completer c = completerQueue.removeAt(0);
+ c.complete(r);
+ break;
+{%- endif %}
+{%- endfor %}
+ default:
+ throw new Exception("Unexpected message name");
+ break;
+ }
+ }
+}
+
+
+class {{interface.name}}Interface extends bindings.Interface {
+ {{interface.name}}Interface(core.MojoMessagePipeEndpoint endpoint) : super(endpoint);
+
+ bindings.Message handleMessage(bindings.MessageReader reader,
+ Function messageHandler) {
+ switch (reader.name) {
+{%- for method in interface.methods %}
+ case k{{interface.name}}_{{method.name}}_name:
+ var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
+{%- if method.response_parameters == None %}
+ messageHandler(params);
+{%- else %}
+ var response = messageHandler(params);
+ return buildResponseWithID(
+ {{interface.name}}_{{method.name}}_ResponseParams,
+ k{{interface.name}}_{{method.name}}_name,
+ bindings.kMessageIsResponse,
+ response);
+{%- endif %}
+ break;
+{%- endfor %}
+ default:
+ throw new Exception("Unexpected message name");
+ break;
+ }
+ return null;
+ }
+}
+
+
+{#--- TODO(zra): Validation #}
+
+
+{#--- Interface Constants #}
+{% for constant in interface.constants %}
+final {{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+
+{#--- Interface Enums #}
+{%- from "enum_definition.tmpl" import enum_def -%}
+{%- for enum in interface.enums %}
+ {{ enum_def("", enum) }}
+{%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl b/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl
new file mode 100644
index 0000000..17e1b78
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library {{module.name}};
+
+import 'dart:async';
+
+import 'package:mojo/public/dart/core.dart' as core;
+import 'package:mojo/public/dart/bindings.dart' as bindings;
+{%- for import in imports %}
+import 'package:{{import.module.path}}.dart' as {{import.unique_name}};
+{%- endfor %}
+
+{%- include "module_definition.tmpl" %}
diff --git a/mojo/public/tools/bindings/generators/dart_templates/module_definition.tmpl b/mojo/public/tools/bindings/generators/dart_templates/module_definition.tmpl
new file mode 100644
index 0000000..e425463
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/dart_templates/module_definition.tmpl
@@ -0,0 +1,20 @@
+{#--- Constants #}
+{%- for constant in module.constants %}
+final {{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+{#--- Enums #}
+{%- from "enum_definition.tmpl" import enum_def %}
+{%- for enum in enums %}
+{{ enum_def("", enum) }}
+{%- endfor %}
+
+{#--- Struct definitions #}
+{% for struct in structs %}
+{%- include "struct_definition.tmpl" %}
+{%- endfor -%}
+
+{#--- Interface definitions #}
+{%- for interface in interfaces -%}
+{%- include "interface_definition.tmpl" %}
+{%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
new file mode 100644
index 0000000..632a99c
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
@@ -0,0 +1,74 @@
+{#--- Begin #}
+
+class {{struct.name}} implements bindings.MojoType<{{struct.name}}> {
+{#--- Enums #}
+{%- from "enum_definition.tmpl" import enum_def %}
+{% for enum in struct.enums %}
+ {{enum_def(" static ", enum)}}
+{%- endfor %}
+
+
+{#--- Constants #}
+{% for constant in struct.constants %}
+ static final {{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+
+{#--- initDefaults() #}
+{%- for packed_field in struct.packed.packed_fields %}
+ {{packed_field.field.kind|dart_decl_type}} {{packed_field.field.name}} = {{packed_field.field|default_value}};
+{%- endfor %}
+
+ {{struct.name}}();
+
+{#--- Encoding and decoding #}
+
+ static const int encodedSize =
+ bindings.kStructHeaderSize + {{struct.packed|payload_size}};
+
+ static {{struct.name}} decode(bindings.MojoDecoder decoder) {
+ var packed;
+ var val = new {{struct.name}}();
+ var numberOfBytes = decoder.readUint32();
+ var numberOfFields = decoder.readUint32();
+{%- for byte in struct.bytes %}
+{%- if byte.packed_fields|length > 1 %}
+ packed = decoder.readUint8();
+{%- for packed_field in byte.packed_fields %}
+ val.{{packed_field.field.name}} = (((packed >> {{packed_field.bit}}) & 1) != 0) ? true : false;
+{%- endfor %}
+{%- else %}
+{%- for packed_field in byte.packed_fields %}
+ val.{{packed_field.field.name}} = decoder.{{packed_field.field.kind|decode_snippet}};
+{%- endfor %}
+{%- endif %}
+{%- if byte.is_padding %}
+ decoder.skip(1);
+{%- endif %}
+{%- endfor %}
+ return val;
+ }
+
+ static void encode(bindings.MojoEncoder encoder, {{struct.name}} val) {
+ var packed;
+ encoder.writeUint32({{struct.name}}.encodedSize);
+ encoder.writeUint32({{struct.packed.packed_fields|length}});
+
+{%- for byte in struct.bytes %}
+{%- if byte.packed_fields|length > 1 %}
+ packed = 0;
+{%- for packed_field in byte.packed_fields %}
+ packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}};
+{%- endfor %}
+ encoder.writeUint8(packed);
+{%- else %}
+{%- for packed_field in byte.packed_fields %}
+ encoder.{{packed_field.field.kind|encode_snippet}}val.{{packed_field.field.name}});
+{%- endfor %}
+{%- endif %}
+{%- if byte.is_padding %}
+ encoder.skip(1);
+{%- endif %}
+{%- endfor %}
+ }
+} \ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
index 27c7cf3..9462e8f 100644
--- a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
@@ -6,6 +6,10 @@
this.receiver_ = receiver;
}
+ {{interface.name}}Proxy.prototype.getConnection$ = function() {
+ return connection.getProxyConnection(this, {{interface.name}});
+ }
+
{%- for method in interface.methods %}
{{interface.name}}Proxy.prototype.{{method.name|stylize_method}} = function(
{%- for parameter in method.parameters -%}
@@ -14,7 +18,19 @@
) {
var params = new {{interface.name}}_{{method.name}}_Params();
{%- for parameter in method.parameters %}
+{%- if parameter|is_interface_parameter %}
+ if ({{parameter.name}} instanceof {{parameter.kind|js_type}}.stubClass)
+ params.{{parameter.name}} = {{parameter.name}}.getConnection$().messagePipeHandle;
+ else
+ params.{{parameter.name}} = {{parameter.name}};
+{%- elif parameter|is_interface_request_parameter %}
+ if ({{parameter.name}} instanceof {{parameter.kind.kind|js_type}}.proxyClass)
+ params.{{parameter.name}} = {{parameter.name}}.getConnection$().messagePipeHandle;
+ else
+ params.{{parameter.name}} = {{parameter.name}};
+{%- else %}
params.{{parameter.name}} = {{parameter.name}};
+{%- endif %}
{%- endfor %}
{%- if method.response_parameters == None %}
@@ -45,8 +61,25 @@
};
{%- endfor %}
- function {{interface.name}}Stub() {
+ function {{interface.name}}Stub(delegate) {
+ this.delegate$ = delegate;
+ }
+
+ {{interface.name}}Stub.prototype.getConnection$ = function() {
+ return connection.getStubConnection(this, {{interface.name}});
+ }
+
+{%- for method in interface.methods %}
+{% macro stub_method_parameters() -%}
+{%- for parameter in method.parameters -%}
+ {{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor %}
+{%- endmacro %}
+ {{interface.name}}Stub.prototype.{{method.name|stylize_method}} = function({{stub_method_parameters()}}) {
+ if (this.delegate$.{{method.name|stylize_method}})
+ return this.delegate$.{{method.name|stylize_method}}({{stub_method_parameters()}});
}
+{%- endfor %}
{{interface.name}}Stub.prototype.accept = function(message) {
var reader = new codec.MessageReader(message);
@@ -57,7 +90,7 @@
var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
this.{{method.name|stylize_method}}(
{%- for parameter in method.parameters -%}
-params.{{parameter.name}}{% if not loop.last %}, {% endif %}
+ params.{{parameter.name}}{% if not loop.last %}, {% endif %}
{%- endfor %});
return true;
{%- endif %}
@@ -100,24 +133,6 @@ params.{{parameter.name}}{% if not loop.last %}, {% endif -%}
}
};
- function {{interface.name}}DelegatingStub() {
- }
-
- {{interface.name}}DelegatingStub.prototype =
- Object.create({{interface.name}}Stub.prototype);
-
- {{interface.name}}DelegatingStub.prototype.callDelegateMethod$ = function(methodName, args) {
- var method = this.delegate$ && this.delegate$[methodName];
- return method && method.apply(this.delegate$, args);
- }
-
-{%- for method in interface.methods %}
-{%- set method_name = method.name|stylize_method %}
- {{interface.name}}DelegatingStub.prototype.{{method_name}} = function() {
- return this.callDelegateMethod$("{{method_name}}", arguments);
- }
-{%- endfor %}
-
{#--- Validation #}
function validate{{interface.name}}Request(messageValidator) {
@@ -171,7 +186,6 @@ params.{{parameter.name}}{% if not loop.last %}, {% endif -%}
name: '{{namespace|replace(".","::")}}::{{interface.name}}',
proxyClass: {{interface.name}}Proxy,
stubClass: {{interface.name}}Stub,
- delegatingStubClass: {{interface.name}}DelegatingStub,
validateRequest: validate{{interface.name}}Request,
{%- if interface|has_callbacks %}
validateResponse: validate{{interface.name}}Response,
diff --git a/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl b/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
index 697eabe..c76d2e9 100644
--- a/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
@@ -4,11 +4,12 @@
define("{{module.path}}", [
"mojo/public/js/codec",
+ "mojo/public/js/connection",
"mojo/public/js/validator",
{%- for import in imports %}
"{{import.module.path}}",
{%- endfor %}
-], function(codec, validator
+], function(codec, connection, validator
{%- for import in imports -%}
, {{import.unique_name}}
{%- endfor -%}
diff --git a/mojo/public/tools/bindings/generators/js_templates/module.sky.tmpl b/mojo/public/tools/bindings/generators/js_templates/module.sky.tmpl
index 14b0d67..5864cfb 100644
--- a/mojo/public/tools/bindings/generators/js_templates/module.sky.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/module.sky.tmpl
@@ -3,6 +3,7 @@
found in the LICENSE file. -->
<import src="/mojo/public/sky/codec.sky" as="codec" />
+<import src="/mojo/public/sky/connection.sky" as="connection" />
<import src="/mojo/public/sky/validator.sky" as="validator" />
{%- for import in imports %}
<import src="/{{import.module.path}}.sky" as="{{import.unique_name}}" />
diff --git a/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/mojo/public/tools/bindings/generators/mojom_dart_generator.py
new file mode 100644
index 0000000..6c1fed3
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/mojom_dart_generator.py
@@ -0,0 +1,295 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates Dart source files from a mojom.Module."""
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+import mojom.generate.pack as pack
+from mojom.generate.template_expander import UseJinja
+
+_kind_to_dart_default_value = {
+ mojom.BOOL: "false",
+ mojom.INT8: "0",
+ mojom.UINT8: "0",
+ mojom.INT16: "0",
+ mojom.UINT16: "0",
+ mojom.INT32: "0",
+ mojom.UINT32: "0",
+ mojom.FLOAT: "0.0",
+ mojom.HANDLE: "null",
+ mojom.DCPIPE: "null",
+ mojom.DPPIPE: "null",
+ mojom.MSGPIPE: "null",
+ mojom.SHAREDBUFFER: "null",
+ mojom.NULLABLE_HANDLE: "null",
+ mojom.NULLABLE_DCPIPE: "null",
+ mojom.NULLABLE_DPPIPE: "null",
+ mojom.NULLABLE_MSGPIPE: "null",
+ mojom.NULLABLE_SHAREDBUFFER: "null",
+ mojom.INT64: "0",
+ mojom.UINT64: "0",
+ mojom.DOUBLE: "0.0",
+ mojom.STRING: "null",
+ mojom.NULLABLE_STRING: "null"
+}
+
+
+_kind_to_dart_decl_type = {
+ mojom.BOOL: "bool",
+ mojom.INT8: "int",
+ mojom.UINT8: "int",
+ mojom.INT16: "int",
+ mojom.UINT16: "int",
+ mojom.INT32: "int",
+ mojom.UINT32: "int",
+ mojom.FLOAT: "double",
+ mojom.HANDLE: "RawMojoHandle",
+ mojom.DCPIPE: "RawMojoHandle",
+ mojom.DPPIPE: "RawMojoHandle",
+ mojom.MSGPIPE: "RawMojoHandle",
+ mojom.SHAREDBUFFER: "RawMojoHandle",
+ mojom.NULLABLE_HANDLE: "RawMojoHandle",
+ mojom.NULLABLE_DCPIPE: "RawMojoHandle",
+ mojom.NULLABLE_DPPIPE: "RawMojoHandle",
+ mojom.NULLABLE_MSGPIPE: "RawMojoHandle",
+ mojom.NULLABLE_SHAREDBUFFER: "RawMojoHandle",
+ mojom.INT64: "int",
+ mojom.UINT64: "int",
+ mojom.DOUBLE: "double",
+ mojom.STRING: "String",
+ mojom.NULLABLE_STRING: "String"
+}
+
+
+def DartType(kind):
+ if kind.imported_from:
+ return kind.imported_from["unique_name"] + "." + kind.name
+ return kind.name
+
+
+def DartDefaultValue(field):
+ if field.default:
+ if mojom.IsStructKind(field.kind):
+ assert field.default == "default"
+ return "new %s()" % DartType(field.kind)
+ return ExpressionToText(field.default)
+ if field.kind in mojom.PRIMITIVES:
+ return _kind_to_dart_default_value[field.kind]
+ if mojom.IsStructKind(field.kind):
+ return "null"
+ if mojom.IsArrayKind(field.kind):
+ return "null"
+ if mojom.IsMapKind(field.kind):
+ return "null"
+ if mojom.IsInterfaceKind(field.kind) or \
+ mojom.IsInterfaceRequestKind(field.kind):
+ return _kind_to_dart_default_value[mojom.MSGPIPE]
+ if mojom.IsEnumKind(field.kind):
+ return "0"
+
+
+def DartDeclType(kind):
+ if kind in mojom.PRIMITIVES:
+ return _kind_to_dart_decl_type[kind]
+ if mojom.IsStructKind(kind):
+ return DartType(kind)
+ if mojom.IsArrayKind(kind):
+ array_type = DartDeclType(kind.kind)
+ return "List<" + array_type + ">"
+ if mojom.IsMapKind(kind):
+ key_type = DartDeclType(kind.key_kind)
+ value_type = DartDeclType(kind.value_kind)
+ return "Map<"+ key_type + ", " + value_type + ">"
+ if mojom.IsInterfaceKind(kind) or \
+ mojom.IsInterfaceRequestKind(kind):
+ return _kind_to_dart_decl_type[mojom.MSGPIPE]
+ if mojom.IsEnumKind(kind):
+ return "int"
+
+def DartPayloadSize(packed):
+ packed_fields = packed.packed_fields
+ if not packed_fields:
+ return 0
+ last_field = packed_fields[-1]
+ offset = last_field.offset + last_field.size
+ pad = pack.GetPad(offset, 8)
+ return offset + pad
+
+
+_kind_to_codec_type = {
+ mojom.BOOL: "bindings.Uint8",
+ mojom.INT8: "bindings.Int8",
+ mojom.UINT8: "bindings.Uint8",
+ mojom.INT16: "bindings.Int16",
+ mojom.UINT16: "bindings.Uint16",
+ mojom.INT32: "bindings.Int32",
+ mojom.UINT32: "bindings.Uint32",
+ mojom.FLOAT: "bindings.Float",
+ mojom.HANDLE: "bindings.Handle",
+ mojom.DCPIPE: "bindings.Handle",
+ mojom.DPPIPE: "bindings.Handle",
+ mojom.MSGPIPE: "bindings.Handle",
+ mojom.SHAREDBUFFER: "bindings.Handle",
+ mojom.NULLABLE_HANDLE: "bindings.NullableHandle",
+ mojom.NULLABLE_DCPIPE: "bindings.NullableHandle",
+ mojom.NULLABLE_DPPIPE: "bindings.NullableHandle",
+ mojom.NULLABLE_MSGPIPE: "bindings.NullableHandle",
+ mojom.NULLABLE_SHAREDBUFFER: "bindings.NullableHandle",
+ mojom.INT64: "bindings.Int64",
+ mojom.UINT64: "bindings.Uint64",
+ mojom.DOUBLE: "bindings.Double",
+ mojom.STRING: "bindings.MojoString",
+ mojom.NULLABLE_STRING: "bindings.NullableMojoString",
+}
+
+
+def CodecType(kind):
+ if kind in mojom.PRIMITIVES:
+ return _kind_to_codec_type[kind]
+ if mojom.IsStructKind(kind):
+ pointer_type = "NullablePointerTo" if mojom.IsNullableKind(kind) \
+ else "PointerTo"
+ return "new bindings.%s(%s)" % (pointer_type, DartType(kind))
+ if mojom.IsArrayKind(kind):
+ array_type = "NullableArrayOf" if mojom.IsNullableKind(kind) else "ArrayOf"
+ array_length = "" if kind.length is None else ", %d" % kind.length
+ element_type = "bindings.PackedBool" if mojom.IsBoolKind(kind.kind) \
+ else CodecType(kind.kind)
+ return "new bindings.%s(%s%s)" % (array_type, element_type, array_length)
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return CodecType(mojom.MSGPIPE)
+ if mojom.IsEnumKind(kind):
+ return _kind_to_codec_type[mojom.INT32]
+ return kind
+
+def MapCodecType(kind):
+ return "bindings.PackedBool" if mojom.IsBoolKind(kind) else CodecType(kind)
+
+def DartDecodeSnippet(kind):
+ if kind in mojom.PRIMITIVES:
+ return "decodeStruct(%s)" % CodecType(kind)
+ if mojom.IsStructKind(kind):
+ return "decodeStructPointer(%s)" % DartType(kind)
+ if mojom.IsMapKind(kind):
+ return "decodeMapPointer(%s, %s)" % \
+ (MapCodecType(kind.key_kind), MapCodecType(kind.value_kind))
+ if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
+ return "decodeArrayPointer(bindings.PackedBool)"
+ if mojom.IsArrayKind(kind):
+ return "decodeArrayPointer(%s)" % CodecType(kind.kind)
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return DartDecodeSnippet(mojom.MSGPIPE)
+ if mojom.IsEnumKind(kind):
+ return DartDecodeSnippet(mojom.INT32)
+
+
+def DartEncodeSnippet(kind):
+ if kind in mojom.PRIMITIVES:
+ return "encodeStruct(%s, " % CodecType(kind)
+ if mojom.IsStructKind(kind):
+ return "encodeStructPointer(%s, " % DartType(kind)
+ if mojom.IsMapKind(kind):
+ return "encodeMapPointer(%s, %s, " % \
+ (MapCodecType(kind.key_kind), MapCodecType(kind.value_kind))
+ if mojom.IsArrayKind(kind) and mojom.IsBoolKind(kind.kind):
+ return "encodeArrayPointer(bindings.PackedBool, ";
+ if mojom.IsArrayKind(kind):
+ return "encodeArrayPointer(%s, " % CodecType(kind.kind)
+ if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind):
+ return DartEncodeSnippet(mojom.MSGPIPE)
+ if mojom.IsEnumKind(kind):
+ return DartEncodeSnippet(mojom.INT32)
+
+
+def TranslateConstants(token):
+ if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
+ # Both variable and enum constants are constructed like:
+ # NamespaceUid.Struct.Enum_CONSTANT_NAME
+ name = ""
+ if token.imported_from:
+ name = token.imported_from["unique_name"] + "."
+ if token.parent_kind:
+ name = name + token.parent_kind.name + "."
+ if isinstance(token, mojom.EnumValue):
+ name = name + token.enum.name + "_"
+ return name + token.name
+
+ if isinstance(token, mojom.BuiltinValue):
+ if token.value == "double.INFINITY" or token.value == "float.INFINITY":
+ return "double.INFINITY";
+ if token.value == "double.NEGATIVE_INFINITY" or \
+ token.value == "float.NEGATIVE_INFINITY":
+ return "double.NEGATIVE_INFINITY";
+ if token.value == "double.NAN" or token.value == "float.NAN":
+ return "double.NAN";
+
+ # Strip leading '+'.
+ if token[0] == '+':
+ token = token[1:]
+
+ return token
+
+
+def ExpressionToText(value):
+ return TranslateConstants(value)
+
+
+class Generator(generator.Generator):
+
+ dart_filters = {
+ "default_value": DartDefaultValue,
+ "payload_size": DartPayloadSize,
+ "decode_snippet": DartDecodeSnippet,
+ "encode_snippet": DartEncodeSnippet,
+ "expression_to_text": ExpressionToText,
+ "dart_decl_type": DartDeclType,
+ "stylize_method": generator.StudlyCapsToCamel,
+ }
+
+ def GetParameters(self):
+ return {
+ "namespace": self.module.namespace,
+ "imports": self.GetImports(),
+ "kinds": self.module.kinds,
+ "enums": self.module.enums,
+ "module": self.module,
+ "structs": self.GetStructs() + self.GetStructsFromMethods(),
+ "interfaces": self.module.interfaces,
+ "imported_interfaces": self.GetImportedInterfaces(),
+ }
+
+ @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)
+ def GenerateLibModule(self):
+ return self.GetParameters()
+
+ def GenerateFiles(self, args):
+ self.Write(self.GenerateLibModule(),
+ self.MatchMojomFilePath("%s.dart" % self.module.name))
+
+ def GetImports(self):
+ used_names = set()
+ for each_import in self.module.imports:
+ simple_name = each_import["module_name"].split(".")[0]
+
+ # Since each import is assigned a variable in JS, they need to have unique
+ # names.
+ unique_name = simple_name
+ counter = 0
+ while unique_name in used_names:
+ counter += 1
+ unique_name = simple_name + str(counter)
+
+ used_names.add(unique_name)
+ each_import["unique_name"] = unique_name
+ counter += 1
+ return self.module.imports
+
+ def GetImportedInterfaces(self):
+ interface_to_import = {};
+ for each_import in self.module.imports:
+ for each_interface in each_import["module"].interfaces:
+ name = each_interface.name
+ interface_to_import[name] = each_import["unique_name"] + "." + name
+ return interface_to_import;
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index 47fea23..7ff6759 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -249,7 +249,6 @@ def TranslateConstants(token):
def ExpressionToText(value):
return TranslateConstants(value)
-
def IsArrayPointerField(field):
return mojom.IsArrayKind(field.kind)
@@ -265,6 +264,12 @@ def IsMapPointerField(field):
def IsHandleField(field):
return mojom.IsAnyHandleKind(field.kind)
+def IsInterfaceRequestParameter(parameter):
+ return mojom.IsInterfaceRequestKind(parameter.kind)
+
+def IsInterfaceParameter(parameter):
+ return mojom.IsInterfaceKind(parameter.kind)
+
class Generator(generator.Generator):
@@ -282,6 +287,8 @@ class Generator(generator.Generator):
"is_string_pointer_field": IsStringPointerField,
"is_handle_field": IsHandleField,
"js_type": JavaScriptType,
+ "is_interface_request_parameter": IsInterfaceRequestParameter,
+ "is_interface_parameter": IsInterfaceParameter,
"stylize_method": generator.StudlyCapsToCamel,
"validate_array_params": JavaScriptValidateArrayParams,
"validate_handle_params": JavaScriptValidateHandleParams,
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index 5a7932e..69f4b76 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -47,6 +47,11 @@ template("mojom") {
"$generator_root/generators/cpp_templates/struct_macros.tmpl",
"$generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
"$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
+ "$generator_root/generators/dart_templates/enum_definition.tmpl",
+ "$generator_root/generators/dart_templates/interface_definition.tmpl",
+ "$generator_root/generators/dart_templates/module.lib.tmpl",
+ "$generator_root/generators/dart_templates/module_definition.tmpl",
+ "$generator_root/generators/dart_templates/struct_definition.tmpl",
"$generator_root/generators/java_templates/constant_definition.tmpl",
"$generator_root/generators/java_templates/constants.java.tmpl",
"$generator_root/generators/java_templates/enum.java.tmpl",
@@ -66,6 +71,7 @@ template("mojom") {
"$generator_root/generators/python_templates/module_macros.tmpl",
"$generator_root/generators/python_templates/module.py.tmpl",
"$generator_root/generators/mojom_cpp_generator.py",
+ "$generator_root/generators/mojom_dart_generator.py",
"$generator_root/generators/mojom_js_generator.py",
"$generator_root/generators/mojom_java_generator.py",
"$generator_root/generators/mojom_python_generator.py",
@@ -88,6 +94,9 @@ template("mojom") {
"{{source_gen_dir}}/{{source_name_part}}.mojom.h",
"{{source_gen_dir}}/{{source_name_part}}.mojom-internal.h",
]
+ generator_dart_outputs = [
+ "{{source_gen_dir}}/{{source_name_part}}.mojom.dart",
+ ]
generator_java_outputs = [
"{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar",
]
@@ -114,6 +123,7 @@ template("mojom") {
inputs = generator_sources
sources = invoker.sources
outputs = generator_cpp_outputs +
+ generator_dart_outputs +
generator_java_outputs +
generator_js_outputs +
generator_python_outputs
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py
index cccc42a..7dc9067 100755
--- a/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -50,6 +50,9 @@ def LoadGenerators(generators_string):
if generator_name.lower() == "c++":
generator_name = os.path.join(script_dir, "generators",
"mojom_cpp_generator.py")
+ if generator_name.lower() == "dart":
+ generator_name = os.path.join(script_dir, "generators",
+ "mojom_dart_generator.py")
elif generator_name.lower() == "javascript":
generator_name = os.path.join(script_dir, "generators",
"mojom_js_generator.py")
@@ -170,7 +173,7 @@ def main():
help="output directory for generated files")
parser.add_argument("-g", "--generators", dest="generators_string",
metavar="GENERATORS",
- default="c++,javascript,java,python",
+ default="c++,dart,javascript,java,python",
help="comma-separated list of generators")
parser.add_argument("--debug_print_intermediate", action="store_true",
help="print the intermediate representation")
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
index 85c9105..4aca497 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/data.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py
@@ -128,9 +128,17 @@ def KindFromData(kinds, data, scope):
elif data.startswith('r:'):
kind = mojom.InterfaceRequest(KindFromData(kinds, data[2:], scope))
elif data.startswith('m['):
- # Isolate the two types from their brackets
- first_kind = data[2:data.find(']')]
- second_kind = data[data.rfind('[')+1:data.rfind(']')]
+ # Isolate the two types from their brackets.
+
+ # It is not allowed to use map as key, so there shouldn't be nested ']'s
+ # inside the key type spec.
+ key_end = data.find(']')
+ assert key_end != -1 and key_end < len(data) - 1
+ assert data[key_end+1] == '[' and data[-1] == ']'
+
+ first_kind = data[2:key_end]
+ second_kind = data[key_end+2:-1]
+
kind = mojom.Map(KindFromData(kinds, first_kind, scope),
KindFromData(kinds, second_kind, scope))
else:
diff --git a/mojo/public/tools/download_shell_binary.py b/mojo/public/tools/download_shell_binary.py
index e28034c..2a0890c 100755
--- a/mojo/public/tools/download_shell_binary.py
+++ b/mojo/public/tools/download_shell_binary.py
@@ -25,6 +25,7 @@ stamp_path = os.path.join(prebuilt_file_path, "VERSION")
depot_tools_path = find_depot_tools.add_depot_tools_to_path()
gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
+
def download():
version_path = os.path.join(current_path, "../VERSION")
with open(version_path) as version_file:
@@ -38,17 +39,39 @@ def download():
except IOError:
pass # If the stamp file does not exist we need to download a new binary.
- platform = "linux-x64" # TODO: configurate
+ platform = "linux-x64" # TODO: configurate
basename = platform + ".zip"
gs_path = "gs://mojo/shell/" + version + "/" + basename
with tempfile.NamedTemporaryFile() as temp_zip_file:
- subprocess.check_call([gsutil_exe, "--bypass_prodaccess",
- "cp", gs_path, temp_zip_file.name])
+ # We're downloading from a public bucket which does not need authentication,
+ # but the user might have busted credential files somewhere such as ~/.boto
+ # that the gsutil script will try (and fail) to use. Setting these
+ # environment variables convinces gsutil not to attempt to use these, but
+ # also generates a useless warning about failing to load the file. We want
+ # to discard this warning but still preserve all output in the case of an
+ # actual failure. So, we run the script and capture all output and then
+ # throw the output away if the script succeeds (return code 0).
+ env = os.environ.copy()
+ env["AWS_CREDENTIAL_FILE"] = ""
+ env["BOTO_CONFIG"] = ""
+ try:
+ subprocess.check_output(
+ [gsutil_exe,
+ "--bypass_prodaccess",
+ "cp",
+ gs_path,
+ temp_zip_file.name],
+ stderr=subprocess.STDOUT,
+ env=env)
+ except subprocess.CalledProcessError as e:
+ print e.output
+ sys.exit(1)
+
with zipfile.ZipFile(temp_zip_file.name) as z:
zi = z.getinfo("mojo_shell")
- mode = zi.external_attr >> 16L
+ mode = zi.external_attr >> 16
z.extract(zi, prebuilt_file_path)
os.chmod(os.path.join(prebuilt_file_path, "mojo_shell"), mode)
@@ -56,9 +79,10 @@ def download():
stamp_file.write(version)
return 0
+
def main():
parser = argparse.ArgumentParser(description="Download mojo_shell binary "
- "from google storage")
+ "from google storage")
parser.parse_args()
return download()