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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | docs/mojom_lang/mojom_lang.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Mojom IDL 1 # Mojom IDL
2 2
3 The Mojom IDL (interface definition language) is primarily used to describe 3 The Mojom IDL (interface definition language) is primarily used to describe
4 *interfaces* to be used on [message pipes](message_pipes.md). Below, we describe 4 *interfaces* to be used on [message pipes](message_pipes.md). Below, we give a
5 practical aspects of the Mojom language. Elsewhere, we describe the [Mojom 5 brief overview of some practical aspects of the Mojom language (for more
6 protocol](mojom_protocol.md). (**TODO(vtl)**: Also, serialization format? 6 details, see the [Mojom language](../mojom_lang/mojom_lang.md). Elsewhere, we
7 Versioning?) 7 describe the [Mojom protocol](mojom_protocol.md). (**TODO(vtl)**: Also,
8 serialization format? Versioning?)
8 9
9 Text files written in Mojom IDL are given the `.mojom` extension by convention 10 Text files written in Mojom IDL are given the `.mojom` extension by convention
10 (and are usually referred to as Mojom/mojom/`.mojom` files). The Mojom bindings 11 (and are usually referred to as Mojom/mojom/`.mojom` files). Mojom IDL permits
11 generator (**TODO(vtl)**: link?) may be used to generate code in a variety of 12 C++-style comments: single-line comments starting with `//` or multi-line
12 languages (including C++, Dart, and Go) from a Mojom file. Such generated code 13 comments enclosed by `/* ... */`.
13 "implements" the things specified in the Mojom file, in a way that's appropriate 14
14 for the particular target language. 15 The Mojom bindings generator (**TODO(vtl)**: link?) may be used to generate code
16 in a variety of languages (including C++, Dart, and Go) from a Mojom file. Such
17 generated code "implements" the things specified in the Mojom file, in a way
18 that's appropriate for the particular target language.
19
20 ## Modules and imports
21
22 A Mojom file begins with an optional *module* declaration, which acts like a C++
23 namespace declaration (applying to the entire file). It is then followed by zero
24 or more *import* statements, which make the contents of the imported files (and,
25 transitively, their imports) available in the current file. For example:
26 ```mojom
27 module my_module.my_submodule;
28
29 import "path/to/another.mojom";
30 import "path/to/yet/a/different.mojom";
31 ```
32
33 ### Name resolution
34
35 Name resolution is basically C++-like (with `.` instead of `::`): Within
36 `my_module.my_submodule`, an unnested declaration of a name `Foo` declares
37 something with "full" name `my_module.my_submodule.Foo`. A *use* of a name `Foo`
38 could either refer to one of the "full" names: `my_module.my_submodule.Foo`,
39 `my_module.Foo`, or `Foo` (searched in that order).
40
41 Nested declarations act in the expected way. E.g., if `Foo` is a struct
42 containing an enum declaration of `Bar`, then `Foo.Bar` (or
43 `my_submodule.Foo.Bar`, or `my_module.my_submodule.Foo.Bar`) can be used to
44 refer to that enum outside of `Foo`.
45
46 ### Names and ordinals
47
48 Generally, at a binary (as opposed to source) level, names in Mojom are not
49 important (except in that they must not collide). Names may be changed without
50 affecting binary compatibility.
51
52 Instead, what's important are *ordinals*, which apply to struct fields
53 (including message request/response parameters) and interface messages. Often,
54 these are left implicit, in which case ordinals are assigned consecutively
55 starting from 0. (Obviously, with implicit declaration, the order of declaration
56 of struct fields, etc. is important.) Ordinals may also be assigned explicitly,
57 using the notation `@123` (for example). (This allows struct fields, etc. to be
58 re-ordered in a Mojom file without breaking binary compatibility.
59
60 Though ordinals are important for evolving Mojom files in a backwards-compatible
61 way, we will not discuss them in this introduction.
62
63 ### Naming style
64
65 Though names are not important, various code generators expect names in a
66 certain *style*, in order to transform them into a style more appropriate for a
67 given target language:
68 * `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union,
69 and enum) type names and message (a.k.a. function or method) names;
70 * `unix_hacker_style` for field names (in structs and unions) and "parameter"
71 names;
72 * `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and
73 * `kStudlyCaps` for const names.
74
75 Following this style is highly recommended (and may be required as a practical
76 matter).
15 77
16 ## Interfaces 78 ## Interfaces
17 79
18 A Mojom *interface* is (typically) used to describe communication on a message 80 A Mojom *interface* is (typically) used to describe communication on a message
19 pipe. Typically, message pipes are created with a particular interface in mind, 81 pipe. Typically, message pipes are created with a particular interface in mind,
20 with one endpoint designated the *client* (which sends *request* messages and 82 with one endpoint designated the *client* (which sends *request* messages and
21 receives *response* messages) and the other designed that *server* or *impl* 83 receives *response* messages) and the other designed that *server* or *impl*
22 (which receives request messages and sends response messages). 84 (which receives request messages and sends response messages).
23 85
24 For example, take the following Mojom interface declaration: 86 For example, take the following Mojom interface declaration:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 of serialization. As we saw above, messages are basically just structs, with a 123 of serialization. As we saw above, messages are basically just structs, with a
62 small amount of additional metadata. 124 small amount of additional metadata.
63 125
64 Here is a simple example of a struct declaration: 126 Here is a simple example of a struct declaration:
65 ```mojom 127 ```mojom
66 struct MyStruct { 128 struct MyStruct {
67 int32 a; 129 int32 a;
68 string b; 130 string b;
69 }; 131 };
70 ``` 132 ```
71 We will discuss in greater detail how structs are declared later. 133 Structs (and interfaces) may also contain enum and const declarations, which
72 134 we will discuss below.
73 ### Names in Mojom 135
74 136 ## Types
75 Names in Mojom are not important. Except in affecting compatibility at the level 137
76 of source code (when generating bindings), names in a Mojom file may be changed 138 ### Non-reference (simple and enum) types
77 arbitrarily without any effect on the "meaning" of the Mojom file (subject to 139
78 basic language requirements, e.g., avoiding collisions with keywords and other 140 We have seen some simple types above, namely `int32`, `uint32`, and `bool`. A
79 names). E.g., the following is completely equivalent to the interface discussed 141 complete list of *simple* types is:
80 above: 142 * `bool`: boolean values;
81 ```mojom 143 * `int8`, `int16`, `int32`, `int64`: signed 2's-complement integers of the given
82 interface Something { 144 size;
83 One(int32 an_integer, string a_string); 145 * `uint8`, `uint16`, `uint32`, `uint64`: unsigned integers of the given size;
84 Two() => (bool a_boolean, uint32 an_unsigned); 146 and
85 Three() => (); 147 * `float`, `double`: single- and double-precision IEEE floating-point numbers.
86 }; 148
87 ``` 149 Additionally, there are *enum* types, which are user-defined. Internally, enums
88 The `Something` interface is compatible at a binary level with `MyInterface`. A 150 are signed 2's complement 32-bit integers, so their values are restricted to
89 client using the `Something` interface may communicate with a server 151 that range. For example:
90 implementing the `MyInterface` with no issues, and vice versa. 152 ```mojom
91
92 The reason for this is that elements (messages, parameters, struct members,
93 etc.) are actually identified by *ordinal* value. They may be specified
94 explicitly (using `@123` notation; see below). If they are not specified
95 explicitly, they are automatically assigned. (The ordinal values for each
96 interface/struct/etc. must assign distinct values for each item, in a
97 consecutive range starting at 0.)
98
99 Explicitly assigning ordinals allows Mojom files to be rearranged "physically"
100 without changing their meaning. E.g., perhaps one would write:
101 ```mojom
102 interface MyInterface {
103 Bar@1() => (bool x@0, uint32 y@1);
104 Baz@2() => ();
105
106 // Please don't use this in new code!
107 FooDeprecated@0(int32 a@0, string b@1);
108 };
109 ```
110
111 Ordinals also tie into the versioning scheme (**TODO(vtl)**: link?), which
112 allows Mojom files to be evolved in a backwards-compatible way. We will not
113 discuss this matter further here.
114
115 **TODO(vtl)**: Maybe mention exceptions to this in attributes (e.g.,
116 `ServiceName`).
117
118 ## Mojom files
119
120 A Mojom file consists of, in order:
121 * an optional *module* declaration;
122 * zero or more *import* statements (the order of these is not important); and
123 * zero or more declarations of *struct*s, *interface*s, *union*s, *enum*s, or
124 *const*s (the order of these is not important).
125 (These are all described further below.)
126
127 Additionally, C/C++-style comments are supported (i.e., single-line comments
128 starting with `//` or multi-line comments of the form `/* ... */`).
129
130 As stated above, the order of struct/interface/union/enum/const declarations is
131 not important. This is required to allow "cyclic" structures to be defined.
132 Nonetheless, whenever possible, one should declare things before they are
133 "used". For example, the following is valid but not recommended:
134 ```mojom
135 // NOT recommended.
136
137 const MyEnum kMyConst = kMyOtherConst;
138 const MyEnum kMyOtherConst = A_VALUE;
139
140 enum MyEnum { 153 enum MyEnum {
141 A_VALUE, 154 ONE_VALUE = 1,
142 ANOTHER_VALUE, 155 ANOTHER_VALUE = -5,
143 }; 156 THIRD_VALUE, // Implicit value of -5 + 1 = -4.
144 ``` 157 A_DUPLICATE_VALUE = THIRD_VALUE,
145 158 };
146 ### Naming style 159 ```
147 160 Such an enum type may be used in a struct. For example:
148 There is a standard style for naming things: 161 ```mojom
149 * `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union, 162 struct AStruct {
150 and enum) type names and message (a.k.a. function or method) names; 163 MyEnum x;
151 * `unix_hacker_style` for field names (in structs and unions) and "parameter" 164 double y;
152 names; 165 };
153 * `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and 166 ```
154 * `kStudlyCaps` for const names. 167 (As previously mentioned, an enum declaration may be nested inside a struct or
155 168 interface declaration.)
156 Following this style is highly recommended, since code generators for various 169
157 languages will expect this style, in order to transform the names into a more 170 Together, the simple and enum types comprise the *non-reference* types. The
158 language-appropriate style. 171 remaining types the *reference* types: *pointer* types and *handle* types.
159 172 Unlike the non-reference types, the reference types all have some notion of
160 ### Module statement 173 "null".
161 174
162 The Mojom *module* statement is just a way of logically grouping Mojom 175 ### Pointer types
163 declarations. For example: 176
164 ```mojom 177 A struct is itself a pointer type, and can be used as a member of another struct
165 module my_module; 178 (or as a request/response parameter, for that matter). For example:
166 ``` 179 ```mojom
167 Mojom modules are similar to C++ namespaces (and the standard C++ code generator
168 would put generated code into the `my_module` namespace), in that there is no
169 implication that the file contains the entirety of the "module" definiton;
170 multiple files may have the same module statement. (There is also no requirement
171 that the module name have anything to do with the file path containing the Mojom
172 file.)
173
174 Mojom module names are hierarchical in that they can be composed of multiple
175 parts separated by `.`. For example:
176 ```mojom
177 module my_module.my_submodule;
178
179 struct MyStruct { 180 struct MyStruct {
180 }; 181 int32 a;
181 ``` 182 string b;
182 Name look-up is similar to C++: E.g., if the current module is 183 };
183 `my_module.my_submodule` then `MyStruct`, `my_submodule.MyStruct`, and 184
184 `my_module.my_submodule.MyStruct` all refer to the above struct, whereas if the 185 struct MySecondStruct {
185 current module is just `my_module` then only the latter two do. 186 MyStruct x;
186 187 MyStruct? y;
187 ### Import declarations 188 };
188 189 ```
189 An *import* declaration makes the declarations from another Mojom file available 190 Here, `x` is a *non-nullable* (i.e., required) field of `MySecondStruct`,
190 in the current Mojom file. Moreover, it operates transitively, in the sense that 191 whereas `y` is *nullable* (i.e., optional).
191 it also makes the imports of the imported file available, etc. The "argument" to 192
192 the import statement is a path to a file. Tools that work with Mojom files are 193 A complete list of pointer types is:
193 typically provided with a search path for importing files (just as a C++ 194 * structs: structs, as discussed above;
194 compiler can be provided with an "include path"), for the purposes of resolving 195 * `string`/`string?`: Unicode strings;
195 these paths. (**TODO(vtl)**: This always includes the current Mojom file's path, 196 * `array<Type>`/`array<Type>?`: variable-size arrays (a.k.a. vectors or lists)
196 right? Is the current path the first path that's searched?) 197 of type "Type" (which may be any type);
197 198 * `array<Type, n>`/`array<Type, n>?`: fixed-size arrays of type "Type" and size
198 For example: 199 "n";
199 ```mojom 200 * `map<KeyType, ValueType>`/`map<KeyType, ValueType>?`: maps (a.k.a.
200 module my_module; 201 dictionaries) of key type "KeyType" (which may be any non-reference type or
201 202 `string`) and value type "ValueType" (which may be any type); and
202 import "path/to/another.mojom"; 203 * unions: see below.
203 import "path/to/yet/a/different.mojom"; 204
204 ``` 205 #### Unions
205 This makes the contents of the two mentioned Mojom files available, together 206
206 with whatever they import, transitively. (Note that names are resolved in the 207 *Unions* are "tagged unions". Union declarations look like struct declarations,
207 way described in the previous section.) 208 but with different meaning. For example:
208 209 ```mojom
209 Import cycles are not permitted (so, e.g., it would be an error if 210 union MyUnion {
210 `path/to/another.mojom` imported the current Mojom file). However, it is 211 int32 a;
211 entirely valid for Mojom files to be imported (transitively) multiple times 212 int32 b;
212 (e.g., it is fine for `path/to/another.mojom` to also import 213 string c;
213 `path/to/yet/a/different.mojom`). 214 };
214 215 ```
215 ### Struct declarations 216 An element of type `MyUnion` must contain either an `int32` (called `a`), an
216 217 `int32` (called `b`), *or* a string called `c`. (Like for structs, `MyUnion z`
217 A Mojom *struct* declaration consists of a finite sequence of *field 218 indicates a non-nullable instance, and `MyUnion?` indicates a nullable instance;
218 declaration*, each of which consists of a *type*, a *name*, and optionally a 219 in the nullable case, `z` may either be null or it must contain one of `a`, `b`,
219 *default value* (if applicable for the given type). (If no default value is 220 or `c`.)
220 declared, then the default is the default value for the field type, typically 0, 221
221 null, or similar.) 222 ### Handle types
222 223
223 Additionally, a struct may contain enum and const declarations (**TODO(vtl)**: 224 #### Raw handle types
224 why not struct/union/interface declarations?). While the order of the field 225
225 declarations (with respect to one another) is important, the ordering of the 226 There are the "raw" *handle* types corresponding to different [Mojo
226 enum/const declarations (with respect to both the field declarations and other 227 handle](handles.md) types, with mostly self-explanatory names: `handle` (any
227 enum/const declarations) is not. (But as before, we recommend declaring things 228 kind of Mojo handle), `handle<message_pipe>`, `handle<data_pipe_consumer>`,
228 before "use".) 229 `handle<data_pipe_producer>`, and `handle<shared_buffer>`. These are used to
229 230 indicate that a given message or struct contains the indicated type of Mojo
230 Here is an example with these elements: 231 handle (recall that messages sent on [Mojo message pipes](message_pipes.md) may
231 ```mojom 232 contain handles in addition to simple data).
232 struct Foo { 233
233 const int8 kSomeConstant = 123; 234 Like the pointer types, these may also be nullable (e.g., `handle?`,
234 235 `handle<message_pipe>?`, etc.), where "null" indicates that no handle is to be
235 enum MyEnum { 236 sent (and may be realized, e.g., as the invalid Mojo handle).
236 A_VALUE, 237
237 ANOTHER_VALUE 238 #### Interface types
238 }; 239
239 240 We have already seen *interface* type declarations. In a message (or struct), it
240 int8 first_field = kSomeConstant; 241 is just a message pipe (endpoint) handle. However, it promises that the *peer*
241 uint32 second_field = 123; 242 implements the given interface. For example:
242 MyEnum etc_etc = A_VALUE; 243 ```mojom
243 float a; // Default value is 0. 244 interface MyFirstInterface {
244 string? b; // Default value is null. 245 Foo() => ();
245 }; 246 };
246 ``` 247
247 (Note that `kSomeConstant` may be referred to as `Foo.kSomeConstant` and, 248 interface MySecondInterface {
248 similarly, `MyEnum` as `Foo.MyEnum`. This is required outside of the `Foo` 249 Bar(MyFirstInterface x);
249 declaration.) 250 Baz(MyFirstInterface& y); // Interface request! See below.
250 251 };
251 ### Interface declarations 252 ```
253 Here, a receiver of a `Bar` message is promised a message pipe handle on which
254 it can send (request) messages from `MyFirstInterface` (and then possibly
255 receive responses). I.e., on receiving a `Bar` message, it may then send `Foo`
256 message on `x` (and then receive the response to `Foo`).
257
258 Like other handle types, instances may be non-nullable or nullable (e.g.,
259 `MyFirstInterface?`).
260
261 #### Interface request types
262
263 *Interface request* types are very much like interface types, and also arise
264 from interface type declarations. They are annotated by a trailing `&`: e.g.,
265 `MyFirstInterface&` (or `MyFirstInterface&?` for the nullable version).
266
267 In a message (or struct), an interface request is also just a message pipe
268 handle. However, it is a promise/"request" that the given message pipe handle
269 implement the given interface (in contrast with the peer implementing it).
270
271 In the above example, the receiver of `Baz` also gets a message pipe handle.
272 However, the receiver is expected to implement `MyFirstInterface` on it (or pass
273 it to someone else who will do so). I.e., `Foo` may be *received* on `y` (and
274 then the response sent on it).
275
276 ## Pipelining
277
278 We saw above that Mojom allows both "interfaces" and "interface requests" to be
279 sent in messages. Consider the following interface:
280 ```mojom
281 interface Foo {
282 // ...
283 };
284
285 interface FooFactory {
286 CreateFoo1() => (Foo foo);
287 CreateFoo2(Foo& foo_request);
288 };
289 ```
290
291 `CreateFoo1` and `CreateFoo2` are functionally very similar: in both cases, the
292 sender will (eventually) be able to send `Foo` messages on some message pipe
293 handle. However, there are some important differences.
294
295 In the case of `CreateFoo1`, the sender is only able to do so upon receiving the
296 response to `CreateFoo1`, since the message pipe handle to which `Foo` messages
297 can be written is contained in the response message to `CreateFoo1`.
298
299 For `CreateFoo2`, the operation is somewhat different. Before sending
300 `CreateFoo2`, the sender creates a message pipe. This consists of two message
301 pipe handles (for peer endpoints), which we'll call `foo` and `foo_request` (the
302 latter of which will be sent in the `CreateFoo2` message). Since message pipes
303 are asynchronous and buffered, the sender can start writing `Foo` messages to
304 `foo` at any time, possibly even before `CreateFoo2` is sent! I.e., it can use
305 `foo` without waiting for a response message. This is referred to as
306 *pipelining*.
307
308 Pipelining is typically more efficient, since it eliminates eliminating the need
309 to wait for a response, and it is often more natural, since receiving the
310 response often entails returning to the message loop. Thus this is generally the
311 preferred pattern for "factories" as in the above example.
312
313 The main caveat is that with pipelining, there is no flow control. The sender of
314 `CreateFoo2` has no indication of when `foo` is actually "ready", though even in
315 the case of `CreateFoo1` there is no real promise that the `foo` in the response
316 is actually "ready". (This is perhaps an indication that flow control should be
317 done on `Foo`, e.g., by having its messages have responses.)
318
319 Relatedly, with pipelining, there is limited opportunity to send back
320 information regarding `foo`. (E.g., the preferred method of signalling error is
321 to simply close `foo_request`.) So if additional information is *needed* to make
322 use of `foo`, perhaps the pattern of `CreateFoo1` is preferable, e.g.:
323 ```mojom
324 CreateFoo() => (Foo foo, NeededInfo info);
325 ```
326
327 ## Consts
252 328
253 **TODO(vtl)** 329 **TODO(vtl)**
254 330
255 ### Union declarations 331 ## Annotations
256 332
257 **TODO(vtl)** 333 **TODO(vtl)**
258 334
259 ### Enum declarations 335 ## See also
260 336
261 **TODO(vtl)** 337 **TODO(vtl)**
262
263 ### Const declarations
264
265 **TODO(vtl)**
266
267 **TODO(vtl)**: Write/(re)organize the sections below.
268
269 ## Data types
270
271 ### Primitive types
272
273 #### Standard types
274
275 #### Enum types
276
277 ### "Pointer" types
278
279 #### Nullability
280
281 #### Strings
282
283 #### Maps
284
285 #### Structs
286
287 #### Arrays
288
289 #### Unions
290
291 ### Handle types
292
293 #### Raw handle types
294
295 #### Interface types
296
297 #### Interface request types
298
299 ## Annotations
300
301 ## Pipelining
OLDNEW
« 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