Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 5d120f8d0a6a597537f8f4d21380e403009d5cd7 [file] [log] [blame] [view]
Yuzhu Shene70d1972017-06-02 16:35:151# Mojo JavaScript Bindings API
Mathias Bynens6c5c87d2024-02-21 12:17:162
Ken Rockot929282c2018-05-02 17:07:293This document is a subset of the [Mojo documentation](/mojo/README.md).
rockotf59d2d62017-04-01 02:49:084
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:405*** note
Alison Gale81f4f2c72024-04-22 19:33:316TODO(crbug.com/40605290): this document mentions deprecated JavaScript bindings.
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:407
8We need to update it to describe the new bindings (bindings_lite).
9***
10
Yuzhu Shene70d1972017-06-02 16:35:1511[TOC]
12
13## Getting Started
Mathias Bynens6c5c87d2024-02-21 12:17:1614
Yuzhu Shene70d1972017-06-02 16:35:1515The bindings API is defined in the `mojo` namespace and implemented in
16`mojo_bindings.js`, which could be generated by the GN target
Yuzhu Shen4ccd2692017-12-11 19:14:2517`//mojo/public/js:bindings`.
Yuzhu Shene70d1972017-06-02 16:35:1518
19When a Mojom IDL file is processed by the bindings generator, JavaScript code is
20emitted in a `.js` file with the name based on the input `.mojom` file. Suppose
21we create the following Mojom file at
22`//services/echo/public/interfaces/echo.mojom`:
23
24```
25module test.echo.mojom;
26
27interface Echo {
28 EchoInteger(int32 value) => (int32 result);
29};
30```
31
32And a GN target to generate the bindings in
33`//services/echo/public/interfaces/BUILD.gn`:
34
35```
36import("//mojo/public/tools/bindings/mojom.gni")
37
38mojom("interfaces") {
39 sources = [
40 "echo.mojom",
41 ]
42}
43```
44
Gary Klassendc9b6252017-08-18 19:57:4645Bindings are generated by building one of these implicitly generated targets
46(where "foo" is the target name):
Mathias Bynens6c5c87d2024-02-21 12:17:1647
48- `foo_js` JavaScript bindings; used as compile-time dependency.
49- `foo_js_data_deps` JavaScript bindings; used as run-time dependency.
Gary Klassendc9b6252017-08-18 19:57:4650
Yuzhu Shene70d1972017-06-02 16:35:1551If we then build this target:
Mathias Bynens6c5c87d2024-02-21 12:17:1652
Yuzhu Shene70d1972017-06-02 16:35:1553```
Gary Klassendc9b6252017-08-18 19:57:4654ninja -C out/r services/echo/public/interfaces:interfaces_js
Yuzhu Shene70d1972017-06-02 16:35:1555```
56
57This will produce several generated source files. The one relevant to JavaScript
58bindings is:
Mathias Bynens6c5c87d2024-02-21 12:17:1659
Yuzhu Shene70d1972017-06-02 16:35:1560```
61out/gen/services/echo/public/interfaces/echo.mojom.js
62```
63
64In order to use the definitions in `echo.mojom`, you will need to include two
65files in your html page using `<script>` tags:
Yuzhu Shene70d1972017-06-02 16:35:1566
Mathias Bynens6c5c87d2024-02-21 12:17:1667- `mojo_bindings.js` **Note: This file must be included before any `.mojom.js`
68 files.**
69- `echo.mojom.js`
70
71```html
72<!doctype html>
Yuzhu Shene70d1972017-06-02 16:35:1573<script src="URL/to/mojo_bindings.js"></script>
74<script src="URL/to/echo.mojom.js"></script>
75<script>
Mathias Bynens6c5c87d2024-02-21 12:17:1676 const echoPtr = new test.echo.mojom.EchoPtr();
77 const echoRequest = mojo.makeRequest(echoPtr);
78 // ...
Yuzhu Shene70d1972017-06-02 16:35:1579</script>
80```
81
82## Interfaces
Mathias Bynens6c5c87d2024-02-21 12:17:1683
Yuzhu Shene70d1972017-06-02 16:35:1584Similar to the C++ bindings API, we have:
Mathias Bynens6c5c87d2024-02-21 12:17:1685
86- `mojo.InterfacePtrInfo` and `mojo.InterfaceRequest` encapsulate two ends of a
Yuzhu Shene70d1972017-06-02 16:35:1587 message pipe. They represent the client end and service end of an interface
88 connection, respectively.
Mathias Bynens6c5c87d2024-02-21 12:17:1689- For each Mojom interface `Foo`, there is a generated `FooPtr` class. It owns
Yuzhu Shene70d1972017-06-02 16:35:1590 an `InterfacePtrInfo`; provides methods to send interface calls using the
91 message pipe handle from the `InterfacePtrInfo`.
Mathias Bynens6c5c87d2024-02-21 12:17:1692- `mojo.Binding` owns an `InterfaceRequest`. It listens on the message pipe
Yuzhu Shene70d1972017-06-02 16:35:1593 handle and dispatches incoming messages to a user-defined interface
94 implementation.
95
96Let's consider the `echo.mojom` example above. The following shows how to create
97an `Echo` interface connection and use it to make a call.
98
Mathias Bynens6c5c87d2024-02-21 12:17:1699```html
100<!doctype html>
Yuzhu Shene70d1972017-06-02 16:35:15101<script src="URL/to/mojo_bindings.js"></script>
102<script src="URL/to/echo.mojom.js"></script>
103<script>
Mathias Bynens6c5c87d2024-02-21 12:17:16104 function EchoImpl() {}
105 EchoImpl.prototype.echoInteger = function (value) {
106 return Promise.resolve({ result: value });
107 };
Yuzhu Shene70d1972017-06-02 16:35:15108
Mathias Bynens6c5c87d2024-02-21 12:17:16109 const echoServicePtr = new test.echo.mojom.EchoPtr();
110 const echoServiceRequest = mojo.makeRequest(echoServicePtr);
111 const echoServiceBinding = new mojo.Binding(
112 test.echo.mojom.Echo,
113 new EchoImpl(),
114 echoServiceRequest,
115 );
116 echoServicePtr.echoInteger({ value: 123 }).then((response) => {
117 console.log(`The result is ${response.value}`);
118 });
Yuzhu Shene70d1972017-06-02 16:35:15119</script>
120```
121
122### Interface Pointers and Requests
Mathias Bynens6c5c87d2024-02-21 12:17:16123
Yuzhu Shene70d1972017-06-02 16:35:15124In the example above, `test.echo.mojom.EchoPtr` is an interface pointer class.
125`EchoPtr` represents the client end of an interface connection. For method
126`EchoInteger` in the `Echo` Mojom interface, there is a corresponding
127`echoInteger` method defined in `EchoPtr`. (Please note that the format of the
128generated method name is `camelCaseWithLowerInitial`.)
129
130There are some control methods shared by all interface pointer classes. For
131example, binding/extracting `InterfacePtrInfo`, setting connection error
132handler, querying version information, etc. In order to avoid name collision,
133they are defined in `mojo.InterfacePtrController` and exposed as the `ptr` field
134of every interface pointer class.
135
136In the example above, `echoServiceRequest` is an `InterfaceRequest` instance. It
137represents the service end of an interface connection.
138
139`mojo.makeRequest` creates a message pipe; populates the output argument (which
140could be an `InterfacePtrInfo` or an interface pointer) with one end of the
141pipe; returns the other end wrapped in an `InterfaceRequest` instance.
142
143### Binding an InterfaceRequest
Mathias Bynens6c5c87d2024-02-21 12:17:16144
Yuzhu Shene70d1972017-06-02 16:35:15145A `mojo.Binding` bridges an implementation of an interface and a message pipe
146endpoint, dispatching incoming messages to the implementation.
147
148In the example above, `echoServiceBinding` listens for incoming `EchoInteger`
149method calls on the messsage pipe, and dispatches those calls to the `EchoImpl`
150instance.
151
152### Receiving Responses
Mathias Bynens6c5c87d2024-02-21 12:17:16153
Yuzhu Shene70d1972017-06-02 16:35:15154Some Mojom interface methods expect a response, such as `EchoInteger`. The
155corresponding JavaScript method returns a Promise. This Promise is resolved when
156the service side sends back a response. It is rejected if the interface is
157disconnected.
158
159### Connection Errors
Mathias Bynens6c5c87d2024-02-21 12:17:16160
Yuzhu Shen92e791aa2017-06-20 20:39:31161If a pipe is disconnected, both endpoints will be able to observe the connection
162error (unless the disconnection is caused by closing/destroying an endpoint, in
163which case that endpoint won't get such a notification). If there are remaining
164incoming messages for an endpoint on disconnection, the connection error won't
165be triggered until the messages are drained.
166
167Pipe disconnecition may be caused by:
Mathias Bynens6c5c87d2024-02-21 12:17:16168
169- Mojo system-level causes: process terminated, resource exhausted, etc.
170- The bindings close the pipe due to a validation error when processing a
Yuzhu Shen92e791aa2017-06-20 20:39:31171 received message.
Mathias Bynens6c5c87d2024-02-21 12:17:16172- The peer endpoint is closed. For example, the remote side is a bound interface
Yuzhu Shen92e791aa2017-06-20 20:39:31173 pointer and it is destroyed.
Yuzhu Shene70d1972017-06-02 16:35:15174
Mathias Bynens6c5c87d2024-02-21 12:17:16175Regardless of the underlying cause, when a connection error is encountered on a
176binding endpoint, that endpoint's **connection error handler** (if set) is
177invoked. This handler may only be invoked _once_ as long as the endpoint is
Yuzhu Shene70d1972017-06-02 16:35:15178bound to the same pipe. Typically clients and implementations use this handler
179to do some kind of cleanup or recovery.
180
Mathias Bynens6c5c87d2024-02-21 12:17:16181```js
Yuzhu Shene70d1972017-06-02 16:35:15182// Assume echoServicePtr is already bound.
Mathias Bynens6c5c87d2024-02-21 12:17:16183echoServicePtr.ptr.setConnectionErrorHandler(function () {
Yuzhu Shene70d1972017-06-02 16:35:15184 DoImportantCleanUp();
185});
186
187// Assume echoServiceBinding is already bound:
Mathias Bynens6c5c87d2024-02-21 12:17:16188echoServiceBinding.setConnectionErrorHandler(function () {
Yuzhu Shene70d1972017-06-02 16:35:15189 DoImportantCleanUpToo();
190});
191```
192
193**Note:** Closing one end of a pipe will eventually trigger a connection error
Mathias Bynens6c5c87d2024-02-21 12:17:16194on the other end. However it's ordered with respect to any other event (_e.g._
Yuzhu Shene70d1972017-06-02 16:35:15195writing a message) on the pipe. Therefore, it is safe to make an `echoInteger`
196call on `echoServicePtr` and reset it immediately (which results in
197disconnection), `echoServiceBinding` will receive the `echoInteger` call before
198it observes the connection error.
199
200## Associated Interfaces
Mathias Bynens6c5c87d2024-02-21 12:17:16201
Yuzhu Shene70d1972017-06-02 16:35:15202An associated interface connection doesn't have its own underlying message pipe.
203It is associated with an existing message pipe (i.e., interface connection).
204
205Similar to the non-associated interface case, we have:
Mathias Bynens6c5c87d2024-02-21 12:17:16206
207- `mojo.AssociatedInterfacePtrInfo` and `mojo.AssociatedInterfaceRequest`
208 encapsulate a _route ID_, representing a logical connection over a message
Yuzhu Shene70d1972017-06-02 16:35:15209 pipe.
Mathias Bynens6c5c87d2024-02-21 12:17:16210- For each Mojom interface `Foo`, there is a generated `FooAssociatedPtr` class.
Yuzhu Shene70d1972017-06-02 16:35:15211 It owns an `AssociatedInterfacePtrInfo`. It is the client side of an
212 interface.
Mathias Bynens6c5c87d2024-02-21 12:17:16213- `mojo.AssociatedBinding` owns an `AssociatedInterfaceRequest`. It listens on
Yuzhu Shene70d1972017-06-02 16:35:15214 the connection and dispatches incoming messages to a user-defined interface
215 implementation.
216
Mathias Bynens6c5c87d2024-02-21 12:17:16217See
218[this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces)
Yuzhu Shene70d1972017-06-02 16:35:15219for more details.
220
221## Automatic and Manual Dependency Loading
Mathias Bynens6c5c87d2024-02-21 12:17:16222
Yuzhu Shene70d1972017-06-02 16:35:15223By default, generated `.mojom.js` files automatically load Mojom dependencies.
224For example, if `foo.mojom` imports `bar.mojom`, loading `foo.mojom.js` will
225insert a `<script>` tag to load `bar.mojom.js`, if it hasn't been loaded.
226
227The URL of `bar.mojom.js` is determined by:
Yuzhu Shene70d1972017-06-02 16:35:15228
Mathias Bynens6c5c87d2024-02-21 12:17:16229- the path of `bar.mojom` relative to the position of `foo.mojom` at build time;
230- the URL of `foo.mojom.js`.
231
232For example, if at build time the two Mojom files are located at:
233
Yuzhu Shene70d1972017-06-02 16:35:15234```
235a/b/c/foo.mojom
236a/b/d/bar.mojom
237```
238
239The URL of `foo.mojom.js` is:
Mathias Bynens6c5c87d2024-02-21 12:17:16240
Yuzhu Shene70d1972017-06-02 16:35:15241```
242http://example.org/scripts/b/c/foo.mojom.js
243```
244
245Then the URL of `bar.mojom.js` is supposed to be:
Mathias Bynens6c5c87d2024-02-21 12:17:16246
Yuzhu Shene70d1972017-06-02 16:35:15247```
248http://example.org/scripts/b/d/bar.mojom.js
249```
250
251If you would like `bar.mojom.js` to live at a different location, you need to
252set `mojo.config.autoLoadMojomDeps` to `false` before loading `foo.mojom.js`,
253and manually load `bar.mojom.js` yourself. Similarly, you need to turn off this
254option if you merge `bar.mojom.js` and `foo.mojom.js` into a single file.
255
Mathias Bynens6c5c87d2024-02-21 12:17:16256```html
Yuzhu Shene70d1972017-06-02 16:35:15257<!-- Automatic dependency loading -->
258<script src="http://example.org/scripts/mojo_bindings.js"></script>
259<script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
260
Yuzhu Shene70d1972017-06-02 16:35:15261<!-- Manual dependency loading -->
262<script src="http://example.org/scripts/mojo_bindings.js"></script>
263<script>
264 mojo.config.autoLoadMojomDeps = false;
265</script>
266<script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
267<script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
268```
269
Mathias Bynens6c5c87d2024-02-21 12:17:16270### Performance Tip: Avoid Loading the Same `.mojom.js` File Multiple Times
271
Yuzhu Shene70d1972017-06-02 16:35:15272If `mojo.config.autoLoadMojomDeps` is set to `true` (which is the default
273value), you might accidentally load the same `.mojom.js` file multiple times if
274you are not careful. Although it doesn't cause fatal errors, it hurts
275performance and therefore should be avoided.
276
Mathias Bynens6c5c87d2024-02-21 12:17:16277```html
Yuzhu Shene70d1972017-06-02 16:35:15278<!-- Assume that mojo.config.autoLoadMojomDeps is set to true: -->
279
280<!-- No duplicate loading; recommended. -->
281<script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
282
283<!-- No duplicate loading, although unnecessary. -->
284<script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
285<script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
286
287<!-- Load bar.mojom.js twice; should be avoided. -->
288<!-- when foo.mojom.js is loaded, it sees that bar.mojom.js is not yet loaded,
289 so it inserts another <script> tag for bar.mojom.js. -->
290<script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
291<script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
292```
293
294If a `.mojom.js` file is loaded for a second time, a warnings will be showed
295using `console.warn()` to bring it to developers' attention.
296
297## Name Formatting
Mathias Bynens6c5c87d2024-02-21 12:17:16298
Yuzhu Shene70d1972017-06-02 16:35:15299As a general rule, Mojom definitions follow the C++ formatting style. To make
300the generated JavaScript bindings conforms to our JavaScript style guide, the
301code generator does the following conversions:
302
Mathias Bynens6c5c87d2024-02-21 12:17:16303| In Mojom | In generated `.mojom.js` |
304| ---------------------- | ------------------------ |
305| `MethodLikeThis` | `methodLikeThis` |
306| `parameter_like_this` | `parameterLikeThis` |
307| `field_like_this` | `fieldLikeThis` |
308| `name_space.like_this` | `nameSpace.likeThis` |
309
310## Downloads
311
312As of Chrome 123.0.6309.0, prebuilt MojoJS archives are available for download
313via
314[Chrome for Testing (CfT) infrastructure](https://developer.chrome.com/blog/chrome-for-testing).
315For every user-facing Chrome release, a correspondingly-versioned ZIP file
316containing the relevant MojoJS bindings can be downloaded at the following URL:
317
318```
319https://storage.googleapis.com/chrome-for-testing-public/123.0.6309.0/mojojs.zip
320```
321
322Replace `123.0.6309.0` with the exact Chrome version you need. Any version in
323[CfT’s `known-good-versions.json`](https://googlechromelabs.github.io/chrome-for-testing/known-good-versions.json)
324greater than or equal to 123.0.6309.0 is guaranteed to have a corresponding
325`mojojs.zip` download available.