Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(282)

Unified Diff: docs/intro/mojom_idl.md

Issue 1769863003: Reorganize/rewrite the Mojom IDL intro. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: clarifications Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | docs/mojom_lang/mojom_lang.md » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: docs/intro/mojom_idl.md
diff --git a/docs/intro/mojom_idl.md b/docs/intro/mojom_idl.md
index 8b49b675c0268caa95f1e9936f17203314b91e5c..f861e4c26becde232fee0f1edca13753756eb43d 100644
--- a/docs/intro/mojom_idl.md
+++ b/docs/intro/mojom_idl.md
@@ -1,17 +1,79 @@
# Mojom IDL
The Mojom IDL (interface definition language) is primarily used to describe
-*interfaces* to be used on [message pipes](message_pipes.md). Below, we describe
-practical aspects of the Mojom language. Elsewhere, we describe the [Mojom
-protocol](mojom_protocol.md). (**TODO(vtl)**: Also, serialization format?
-Versioning?)
+*interfaces* to be used on [message pipes](message_pipes.md). Below, we give a
+brief overview of some practical aspects of the Mojom language (for more
+details, see the [Mojom language](../mojom_lang/mojom_lang.md). Elsewhere, we
+describe the [Mojom protocol](mojom_protocol.md). (**TODO(vtl)**: Also,
+serialization format? Versioning?)
Text files written in Mojom IDL are given the `.mojom` extension by convention
-(and are usually referred to as Mojom/mojom/`.mojom` files). The Mojom bindings
-generator (**TODO(vtl)**: link?) may be used to generate code in a variety of
-languages (including C++, Dart, and Go) from a Mojom file. Such generated code
-"implements" the things specified in the Mojom file, in a way that's appropriate
-for the particular target language.
+(and are usually referred to as Mojom/mojom/`.mojom` files). Mojom IDL permits
+C++-style comments: single-line comments starting with `//` or multi-line
+comments enclosed by `/* ... */`.
+
+The Mojom bindings generator (**TODO(vtl)**: link?) may be used to generate code
+in a variety of languages (including C++, Dart, and Go) from a Mojom file. Such
+generated code "implements" the things specified in the Mojom file, in a way
+that's appropriate for the particular target language.
+
+## Modules and imports
+
+A Mojom file begins with an optional *module* declaration, which acts like a C++
+namespace declaration (applying to the entire file). It is then followed by zero
+or more *import* statements, which make the contents of the imported files (and,
+transitively, their imports) available in the current file. For example:
+```mojom
+module my_module.my_submodule;
+
+import "path/to/another.mojom";
+import "path/to/yet/a/different.mojom";
+```
+
+### Name resolution
+
+Name resolution is basically C++-like (with `.` instead of `::`): Within
+`my_module.my_submodule`, an unnested declaration of a name `Foo` declares
+something with "full" name `my_module.my_submodule.Foo`. A *use* of a name `Foo`
+could either refer to one of the "full" names: `my_module.my_submodule.Foo`,
+`my_module.Foo`, or `Foo` (searched in that order).
+
+Nested declarations act in the expected way. E.g., if `Foo` is a struct
+containing an enum declaration of `Bar`, then `Foo.Bar` (or
+`my_submodule.Foo.Bar`, or `my_module.my_submodule.Foo.Bar`) can be used to
+refer to that enum outside of `Foo`.
+
+### Names and ordinals
+
+Generally, at a binary (as opposed to source) level, names in Mojom are not
+important (except in that they must not collide). Names may be changed without
+affecting binary compatibility.
+
+Instead, what's important are *ordinals*, which apply to struct fields
+(including message request/response parameters) and interface messages. Often,
+these are left implicit, in which case ordinals are assigned consecutively
+starting from 0. (Obviously, with implicit declaration, the order of declaration
+of struct fields, etc. is important.) Ordinals may also be assigned explicitly,
+using the notation `@123` (for example). (This allows struct fields, etc. to be
+re-ordered in a Mojom file without breaking binary compatibility.
+
+Though ordinals are important for evolving Mojom files in a backwards-compatible
+way, we will not discuss them in this introduction.
+
+### Naming style
+
+Though names are not important, various code generators expect names in a
+certain *style*, in order to transform them into a style more appropriate for a
+given target language:
+* `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union,
+ and enum) type names and message (a.k.a. function or method) names;
+* `unix_hacker_style` for field names (in structs and unions) and "parameter"
+ names;
+* `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and
+* `kStudlyCaps` for const names.
+
+Following this style is highly recommended (and may be required as a practical
+matter).
## Interfaces
@@ -68,234 +130,208 @@ struct MyStruct {
string b;
};
```
-We will discuss in greater detail how structs are declared later.
+Structs (and interfaces) may also contain enum and const declarations, which
+we will discuss below.
+
+## Types
-### Names in Mojom
+### Non-reference (simple and enum) types
-Names in Mojom are not important. Except in affecting compatibility at the level
-of source code (when generating bindings), names in a Mojom file may be changed
-arbitrarily without any effect on the "meaning" of the Mojom file (subject to
-basic language requirements, e.g., avoiding collisions with keywords and other
-names). E.g., the following is completely equivalent to the interface discussed
-above:
+We have seen some simple types above, namely `int32`, `uint32`, and `bool`. A
+complete list of *simple* types is:
+* `bool`: boolean values;
+* `int8`, `int16`, `int32`, `int64`: signed 2's-complement integers of the given
+ size;
+* `uint8`, `uint16`, `uint32`, `uint64`: unsigned integers of the given size;
+ and
+* `float`, `double`: single- and double-precision IEEE floating-point numbers.
+
+Additionally, there are *enum* types, which are user-defined. Internally, enums
+are signed 2's complement 32-bit integers, so their values are restricted to
+that range. For example:
```mojom
-interface Something {
- One(int32 an_integer, string a_string);
- Two() => (bool a_boolean, uint32 an_unsigned);
- Three() => ();
+enum MyEnum {
+ ONE_VALUE = 1,
+ ANOTHER_VALUE = -5,
+ THIRD_VALUE, // Implicit value of -5 + 1 = -4.
+ A_DUPLICATE_VALUE = THIRD_VALUE,
};
```
-The `Something` interface is compatible at a binary level with `MyInterface`. A
-client using the `Something` interface may communicate with a server
-implementing the `MyInterface` with no issues, and vice versa.
-
-The reason for this is that elements (messages, parameters, struct members,
-etc.) are actually identified by *ordinal* value. They may be specified
-explicitly (using `@123` notation; see below). If they are not specified
-explicitly, they are automatically assigned. (The ordinal values for each
-interface/struct/etc. must assign distinct values for each item, in a
-consecutive range starting at 0.)
-
-Explicitly assigning ordinals allows Mojom files to be rearranged "physically"
-without changing their meaning. E.g., perhaps one would write:
+Such an enum type may be used in a struct. For example:
```mojom
-interface MyInterface {
- Bar@1() => (bool x@0, uint32 y@1);
- Baz@2() => ();
-
- // Please don't use this in new code!
- FooDeprecated@0(int32 a@0, string b@1);
+struct AStruct {
+ MyEnum x;
+ double y;
};
```
+(As previously mentioned, an enum declaration may be nested inside a struct or
+interface declaration.)
-Ordinals also tie into the versioning scheme (**TODO(vtl)**: link?), which
-allows Mojom files to be evolved in a backwards-compatible way. We will not
-discuss this matter further here.
-
-**TODO(vtl)**: Maybe mention exceptions to this in attributes (e.g.,
-`ServiceName`).
+Together, the simple and enum types comprise the *non-reference* types. The
+remaining types the *reference* types: *pointer* types and *handle* types.
+Unlike the non-reference types, the reference types all have some notion of
+"null".
-## Mojom files
+### Pointer types
-A Mojom file consists of, in order:
-* an optional *module* declaration;
-* zero or more *import* statements (the order of these is not important); and
-* zero or more declarations of *struct*s, *interface*s, *union*s, *enum*s, or
- *const*s (the order of these is not important).
-(These are all described further below.)
-
-Additionally, C/C++-style comments are supported (i.e., single-line comments
-starting with `//` or multi-line comments of the form `/* ... */`).
-
-As stated above, the order of struct/interface/union/enum/const declarations is
-not important. This is required to allow "cyclic" structures to be defined.
-Nonetheless, whenever possible, one should declare things before they are
-"used". For example, the following is valid but not recommended:
+A struct is itself a pointer type, and can be used as a member of another struct
+(or as a request/response parameter, for that matter). For example:
```mojom
-// NOT recommended.
-
-const MyEnum kMyConst = kMyOtherConst;
-const MyEnum kMyOtherConst = A_VALUE;
-
-enum MyEnum {
- A_VALUE,
- ANOTHER_VALUE,
+struct MyStruct {
+ int32 a;
+ string b;
};
-```
-
-### Naming style
-
-There is a standard style for naming things:
-* `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union,
- and enum) type names and message (a.k.a. function or method) names;
-* `unix_hacker_style` for field names (in structs and unions) and "parameter"
- names;
-* `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and
-* `kStudlyCaps` for const names.
-Following this style is highly recommended, since code generators for various
-languages will expect this style, in order to transform the names into a more
-language-appropriate style.
-
-### Module statement
-
-The Mojom *module* statement is just a way of logically grouping Mojom
-declarations. For example:
-```mojom
-module my_module;
-```
-Mojom modules are similar to C++ namespaces (and the standard C++ code generator
-would put generated code into the `my_module` namespace), in that there is no
-implication that the file contains the entirety of the "module" definiton;
-multiple files may have the same module statement. (There is also no requirement
-that the module name have anything to do with the file path containing the Mojom
-file.)
-
-Mojom module names are hierarchical in that they can be composed of multiple
-parts separated by `.`. For example:
-```mojom
-module my_module.my_submodule;
-
-struct MyStruct {
+struct MySecondStruct {
+ MyStruct x;
+ MyStruct? y;
};
```
-Name look-up is similar to C++: E.g., if the current module is
-`my_module.my_submodule` then `MyStruct`, `my_submodule.MyStruct`, and
-`my_module.my_submodule.MyStruct` all refer to the above struct, whereas if the
-current module is just `my_module` then only the latter two do.
-
-### Import declarations
-
-An *import* declaration makes the declarations from another Mojom file available
-in the current Mojom file. Moreover, it operates transitively, in the sense that
-it also makes the imports of the imported file available, etc. The "argument" to
-the import statement is a path to a file. Tools that work with Mojom files are
-typically provided with a search path for importing files (just as a C++
-compiler can be provided with an "include path"), for the purposes of resolving
-these paths. (**TODO(vtl)**: This always includes the current Mojom file's path,
-right? Is the current path the first path that's searched?)
-
-For example:
-```mojom
-module my_module;
+Here, `x` is a *non-nullable* (i.e., required) field of `MySecondStruct`,
+whereas `y` is *nullable* (i.e., optional).
+
+A complete list of pointer types is:
+* structs: structs, as discussed above;
+* `string`/`string?`: Unicode strings;
+* `array<Type>`/`array<Type>?`: variable-size arrays (a.k.a. vectors or lists)
+ of type "Type" (which may be any type);
+* `array<Type, n>`/`array<Type, n>?`: fixed-size arrays of type "Type" and size
+ "n";
+* `map<KeyType, ValueType>`/`map<KeyType, ValueType>?`: maps (a.k.a.
+ dictionaries) of key type "KeyType" (which may be any non-reference type or
+ `string`) and value type "ValueType" (which may be any type); and
+* unions: see below.
-import "path/to/another.mojom";
-import "path/to/yet/a/different.mojom";
-```
-This makes the contents of the two mentioned Mojom files available, together
-with whatever they import, transitively. (Note that names are resolved in the
-way described in the previous section.)
-
-Import cycles are not permitted (so, e.g., it would be an error if
-`path/to/another.mojom` imported the current Mojom file). However, it is
-entirely valid for Mojom files to be imported (transitively) multiple times
-(e.g., it is fine for `path/to/another.mojom` to also import
-`path/to/yet/a/different.mojom`).
-
-### Struct declarations
-
-A Mojom *struct* declaration consists of a finite sequence of *field
-declaration*, each of which consists of a *type*, a *name*, and optionally a
-*default value* (if applicable for the given type). (If no default value is
-declared, then the default is the default value for the field type, typically 0,
-null, or similar.)
-
-Additionally, a struct may contain enum and const declarations (**TODO(vtl)**:
-why not struct/union/interface declarations?). While the order of the field
-declarations (with respect to one another) is important, the ordering of the
-enum/const declarations (with respect to both the field declarations and other
-enum/const declarations) is not. (But as before, we recommend declaring things
-before "use".)
-
-Here is an example with these elements:
+#### Unions
+
+*Unions* are "tagged unions". Union declarations look like struct declarations,
+but with different meaning. For example:
```mojom
-struct Foo {
- const int8 kSomeConstant = 123;
-
- enum MyEnum {
- A_VALUE,
- ANOTHER_VALUE
- };
-
- int8 first_field = kSomeConstant;
- uint32 second_field = 123;
- MyEnum etc_etc = A_VALUE;
- float a; // Default value is 0.
- string? b; // Default value is null.
+union MyUnion {
+ int32 a;
+ int32 b;
+ string c;
};
```
-(Note that `kSomeConstant` may be referred to as `Foo.kSomeConstant` and,
-similarly, `MyEnum` as `Foo.MyEnum`. This is required outside of the `Foo`
-declaration.)
-
-### Interface declarations
-
-**TODO(vtl)**
-
-### Union declarations
+An element of type `MyUnion` must contain either an `int32` (called `a`), an
+`int32` (called `b`), *or* a string called `c`. (Like for structs, `MyUnion z`
+indicates a non-nullable instance, and `MyUnion?` indicates a nullable instance;
+in the nullable case, `z` may either be null or it must contain one of `a`, `b`,
+or `c`.)
-**TODO(vtl)**
-
-### Enum declarations
+### Handle types
-**TODO(vtl)**
+#### Raw handle types
-### Const declarations
+There are the "raw" *handle* types corresponding to different [Mojo
+handle](handles.md) types, with mostly self-explanatory names: `handle` (any
+kind of Mojo handle), `handle<message_pipe>`, `handle<data_pipe_consumer>`,
+`handle<data_pipe_producer>`, and `handle<shared_buffer>`. These are used to
+indicate that a given message or struct contains the indicated type of Mojo
+handle (recall that messages sent on [Mojo message pipes](message_pipes.md) may
+contain handles in addition to simple data).
-**TODO(vtl)**
+Like the pointer types, these may also be nullable (e.g., `handle?`,
+`handle<message_pipe>?`, etc.), where "null" indicates that no handle is to be
+sent (and may be realized, e.g., as the invalid Mojo handle).
-**TODO(vtl)**: Write/(re)organize the sections below.
+#### Interface types
-## Data types
+We have already seen *interface* type declarations. In a message (or struct), it
+is just a message pipe (endpoint) handle. However, it promises that the *peer*
+implements the given interface. For example:
+```mojom
+interface MyFirstInterface {
+ Foo() => ();
+};
-### Primitive types
+interface MySecondInterface {
+ Bar(MyFirstInterface x);
+ Baz(MyFirstInterface& y); // Interface request! See below.
+};
+```
+Here, a receiver of a `Bar` message is promised a message pipe handle on which
+it can send (request) messages from `MyFirstInterface` (and then possibly
+receive responses). I.e., on receiving a `Bar` message, it may then send `Foo`
+message on `x` (and then receive the response to `Foo`).
-#### Standard types
+Like other handle types, instances may be non-nullable or nullable (e.g.,
+`MyFirstInterface?`).
-#### Enum types
+#### Interface request types
-### "Pointer" types
+*Interface request* types are very much like interface types, and also arise
+from interface type declarations. They are annotated by a trailing `&`: e.g.,
+`MyFirstInterface&` (or `MyFirstInterface&?` for the nullable version).
-#### Nullability
+In a message (or struct), an interface request is also just a message pipe
+handle. However, it is a promise/"request" that the given message pipe handle
+implement the given interface (in contrast with the peer implementing it).
-#### Strings
+In the above example, the receiver of `Baz` also gets a message pipe handle.
+However, the receiver is expected to implement `MyFirstInterface` on it (or pass
+it to someone else who will do so). I.e., `Foo` may be *received* on `y` (and
+then the response sent on it).
-#### Maps
+## Pipelining
-#### Structs
+We saw above that Mojom allows both "interfaces" and "interface requests" to be
+sent in messages. Consider the following interface:
+```mojom
+interface Foo {
+ // ...
+};
-#### Arrays
+interface FooFactory {
+ CreateFoo1() => (Foo foo);
+ CreateFoo2(Foo& foo_request);
+};
+```
-#### Unions
+`CreateFoo1` and `CreateFoo2` are functionally very similar: in both cases, the
+sender will (eventually) be able to send `Foo` messages on some message pipe
+handle. However, there are some important differences.
+
+In the case of `CreateFoo1`, the sender is only able to do so upon receiving the
+response to `CreateFoo1`, since the message pipe handle to which `Foo` messages
+can be written is contained in the response message to `CreateFoo1`.
+
+For `CreateFoo2`, the operation is somewhat different. Before sending
+`CreateFoo2`, the sender creates a message pipe. This consists of two message
+pipe handles (for peer endpoints), which we'll call `foo` and `foo_request` (the
+latter of which will be sent in the `CreateFoo2` message). Since message pipes
+are asynchronous and buffered, the sender can start writing `Foo` messages to
+`foo` at any time, possibly even before `CreateFoo2` is sent! I.e., it can use
+`foo` without waiting for a response message. This is referred to as
+*pipelining*.
+
+Pipelining is typically more efficient, since it eliminates eliminating the need
+to wait for a response, and it is often more natural, since receiving the
+response often entails returning to the message loop. Thus this is generally the
+preferred pattern for "factories" as in the above example.
+
+The main caveat is that with pipelining, there is no flow control. The sender of
+`CreateFoo2` has no indication of when `foo` is actually "ready", though even in
+the case of `CreateFoo1` there is no real promise that the `foo` in the response
+is actually "ready". (This is perhaps an indication that flow control should be
+done on `Foo`, e.g., by having its messages have responses.)
+
+Relatedly, with pipelining, there is limited opportunity to send back
+information regarding `foo`. (E.g., the preferred method of signalling error is
+to simply close `foo_request`.) So if additional information is *needed* to make
+use of `foo`, perhaps the pattern of `CreateFoo1` is preferable, e.g.:
+```mojom
+ CreateFoo() => (Foo foo, NeededInfo info);
+```
-### Handle types
+## Consts
-#### Raw handle types
+**TODO(vtl)**
-#### Interface types
+## Annotations
-#### Interface request types
+**TODO(vtl)**
-## Annotations
+## See also
-## Pipelining
+**TODO(vtl)**
« no previous file with comments | « no previous file | docs/mojom_lang/mojom_lang.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698