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

Side by Side Diff: examples/js/users-guide.md

Issue 803173009: Mojo JS Bindings: Eliminate foo$ Stub and Proxy class members (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: sync Created 5 years, 11 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 | « examples/js/README.md ('k') | examples/js/wget.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 JavaScript Mojo Example Applications 1 # Running Mojo Applications
2 =====================
3
4 hello.js, world.js - A minimal application that connects to another.
5
6 wget.js - Uses the network service to load a URL.
7
8 cube.js - A JS version of examples/sample_app.
9
10 --- Running Mojo Applications ---
11 2
12 A Mojo application written in JavaScript is launched with mojo_shell like this: 3 A Mojo application written in JavaScript is launched with mojo_shell like this:
13 4
14 mojo_shell <js-application-url> 5 ```
6 mojo_shell <js-application-url>
7 ```
15 8
16 Where js-application-url is a URL understood by the shell. For example 9 Where js-application-url is a URL understood by the shell. For example
17 a file or an http URL that names a JS source file. The JS file itself 10 a file or an http URL that names a JS source file. The JS file itself
18 must begin with a Mojo "shebang" that specifies the Mojo URL of the JS 11 must begin with a Mojo "shebang" that specifies the Mojo URL of the JS
19 content handler. In other words, the first line of the JS source file 12 content handler. In other words, the first line of the JS source file
20 must be: 13 must be:
21 14
22 #!mojo:js_content_handler 15 ```javascript
16 #!mojo:js_content_handler
17 ```
23 18
24 Following the shebang should be a single AMD module called "main" whose value 19 Following the shebang should be a single AMD module called "main" whose value
25 is an Application subclass. The JS content handler will create an instance of 20 is an Application subclass. The JS content handler will create an instance of
26 the Application and make it the client of the Mojo shell. The JS content handler 21 the Application and make it the client of the Mojo shell. The JS content handler
27 is itself a Mojo application and it's responsible for creating an instance of V8 22 is itself a Mojo application and it's responsible for creating an instance of V8
28 and loading the "main" JS module and all of the modules the main module 23 and loading the "main" JS module and all of the modules the main module
29 depends on. 24 depends on.
30 25
26 ## JavaScript Classes
27
28 The JS content handler depends on the ECMAScript6 ("Harmony") classes feature.
29
30 As of January 2015 Chrome enables Harmony classes by default.
31
32
33 # The JS Application Class
34
35 Mojo JS applications are defined with the Application class. The
36 Application class handles incoming requests for services and provides
37 services of its own.
38
31 This is the overall structure of a JS Mojo application: 39 This is the overall structure of a JS Mojo application:
32 40
33 ```javascript 41 ```javascript
34 #!mojo:js_content_handler 42 #!mojo:js_content_handler
35 43
36 define("main", ["mojo/services/public/js/application", 44 define("main", ["mojo/services/public/js/application",
37 <list of other modules that this application depends on> 45 <list of other modules that this application depends on>
38 ], 46 ],
39 function(appModule, <one parameter per dependent module>) { 47 function(application, <one parameter per dependent module>) {
40 class MyApplication extends appModule.Application { 48 class MyApplication extends application.Application {
41 constructor(appShell, url) { 49 constructor(appShell, url) {
42 super(appShell, url); // Initializes this.shell, this.url. 50 super(appShell, url); // Initializes this.shell, this.url.
43 // MyApplication initializations here. 51 // MyApplication initializations here.
44 } 52 }
45 53
46 initialize(args) { 54 initialize(args) {
47 } 55 }
48 56
49 acceptConnection(url, serviceProvider) { 57 acceptConnection(url, serviceProvider) {
58 }
50 } 59 }
51 } 60 }
52 61
53 return MyApplication; 62 return MyApplication;
54 }); 63 });
55 ``` 64 ```
56 65
57 The hello.js example is little more than this basic skeleton. 66 The hello.js example is little more than this basic skeleton.
58 67
59 The JS content handler loads the "main" module and makes an instance of its 68 The JS content handler loads the "main" module and constructs an
60 value, which must be an Application subclass. The application's constructor is 69 instance of its value, which must be an Application subclass. The
61 passed two arguments: 70 application's constructor is passed two arguments:
62 71
63 appShell - a pointer to the Mojo shell. Typically this will be wrapped by a 72 * `appShell` - a pointer to the Mojo shell. Typically this will be wrapped by a
64 Shell object, see below. 73 JS Shell object, see below.
65 74
66 url - the URL this application was loaded from as a String. 75 * `url` - the URL this application was loaded from as a String.
67 76
68 The (inherited) Application class constructor initializes the shell and url 77 The inherited Application class constructor initializes the shell and url
69 properties. It's unlikely that you'll want to use the appShell argument 78 properties. It's unlikely that you'll want to use the appShell argument
70 directly. 79 directly.
71 80
72 The initialize() and acceptConnection() methods are defined by application.mojom 81 The initialize() and acceptConnection() methods are defined by application.mojom
73 and they're needed because the JS content handler makes the JS application the 82 and they're needed because the JS content handler makes the JS application the
74 Mojo shell's client. 83 Mojo shell's client.
75 84
85 The intiailize() method is called once, after the constructor has run
86 and before any calls to acceptConnection(). The value of its parameter
87 is argument list specified for this application with
88 mojo_shell. Arguments can be specified using the mojo_shell
89 `--args-for` command line argument or by just adding them after the
90 application's URL and enclosing the entire expression in quotes.
76 91
77 --- JavaScript Classes --- 92 ```
93 mojo_shell '<js-application-url> arg1 arg2'
94 ```
95 See the wget.js for an example of command-line argument use.
78 96
79 The JS content handler depends on the ECMAScript6 ("Harmony") classes feature. 97 The acceptConnection() method is called each time another application connects
98 to this one. The first call corresponds the mojo_shell's initial connection.
99 The serviceProvider parameter is a JS ServiceProvider, see the "Requesting
100 and Providing Services" section below.
80 101
102 ## JS Bindings
81 103
104 To use or implement a service you'll need the JS "bindings" for the
105 Mojo interface. The bindings are generated by the build system and end
106 up in files whose name is the same as the '.mojom' file with a '.js'
107 suffix. It's often helpful to look at the generated '.mojom.js' files.
82 108
83 --- Mojo Application Structure ---
84
85 Mojo applications can connect to services provided by other applications and
86 they can provide services of their own. A service is an implementation of a Mojo
87 interface that was defined as part of a Mojo module in a ".mojom" file.
88
89 To implement a service you'll need the JS "bindings" for the Mojo interface. The
90 bindings are generated by the build system and end up in files whose name is the
91 same as the '.mojom' file with a '.js' suffix. It's often helpful to look at the
92 generated 'mojom.js' files.
93
94 The JS Shell class simplifies connecting to applications and services. It's a
95 wrapper for the Application's appShell argument. The Application constructor
96 creates a Shell and assigns it to |this.shell|.
97
98 The Shell's connectToService() method returns a "proxy" to a service provided by
99 another application.
100 109
101 The JS bindings for a Mojo interface's API are delivered as a JS module whose 110 The JS bindings for a Mojo interface's API are delivered as a JS module whose
102 name is based on the '.mojom' file's path. For example, to use the Mojo network 111 name is based on the '.mojom' file's path. For example, to use the Mojo network
103 service you need the JS module based on network_service.mojom: 112 service you need the JS module based on network_service.mojom:
104 113
105 ```javascript 114 ```javascript
106 define("main", [ 115 define("main", [
107 "mojo/services/network/public/interfaces/network_service.mojom", 116 "mojo/services/network/public/interfaces/network_service.mojom",
108 "mojo/services/public/js/application", 117 "mojo/services/public/js/application",
109 ] 118 ]
110 function(netModule, appModule) { 119 function(net, application) {
111 class MyApplication extends appModule.Application { 120 class MyApplication extends application.Application {
112 initialize(args) { 121 initialize(args) {
113 var netService = this.shell.connectToService( 122 var netService = this.shell.connectToService(
114 "mojo:network_service", netModule.NetworkService); 123 "mojo:network_service", net.NetworkService);
115 // Use netService's NetworkService methods. 124 // Use netService's NetworkService methods.
125 }
126 ...
116 } 127 }
117 ... 128 ...
118 } 129 }
119
120 return MyApplication; 130 return MyApplication;
121 }); 131 });
122 ``` 132 ```
123 133
124 The first connectToService() parameter is the Mojo URL for the network service 134 The first connectToService() parameter is the Mojo URL for the network service
125 application and the second is the JS "interface" object for NetworkService. The 135 application and the second is the JS "interface" object for NetworkService. The
126 JS interface object's properties identify the (generated) JS bindings classes 136 JS interface object's properties identify the generated JS bindings classes
127 used to provide or connect to a service. For example (from 137 used to provide or connect to a service. For example (from
128 network_service.mojom.js): 138 network_service.mojom.js):
129 139
130 ```javascript 140 ```javascript
131 var NetworkService = { 141 var NetworkService = {
132 name: 'mojo::NetworkService', // Fully qualified Mojo interface name. 142 name: 'mojo::NetworkService', // Fully qualified Mojo interface name.
133 proxyClass: NetworkServiceProxy, 143 proxyClass: NetworkServiceProxy,
134 stubClass: NetworkServiceStub, 144 stubClass: NetworkServiceStub,
135 // ... 145 // ...
136 }; 146 };
137 ``` 147 ```
138 148
139 The 'proxyClass' is used to access another application's NetworkService and the 149 The 'proxyClass' is used to access another application's NetworkService and the
140 'stubClass' is used to create an implementation of NetworkService. 150 'stubClass' is used to create an implementation of NetworkService.
141 151
152 ## The JS Shell Class
153
154 The JS Shell class simplifies connecting to applications and services. It's a
155 wrapper for the Application's appShell argument. The Application constructor
156 creates a Shell and assigns it to `this.shell`.
157
158 The Shell's connectToService() method returns a "proxy" to a service provided by
159 another application.
160
142 In the netService case above the Shell connects to the Mojo application at 161 In the netService case above the Shell connects to the Mojo application at
143 "mojo:network_service", then connects to its service called 162 "mojo:network_service", then connects to its service called
144 'NetworkService.name' with an instance of 'NetworkService.proxyClass'. The proxy 163 NetworkService.name with an instance of NetworkService.proxyClass. The proxy
145 instance is returned. The netService proxy can be used immediately. 164 instance is returned. The netService proxy can be used immediately.
146 165
147 166
148 --- Mojo Responses are Promises --- 167 ## Mojo Responses are Promises
149 168
150 Mojo functions can return zero or more values called a "response". For example 169 Mojo functions can return zero or more values called a "response". For example
151 the EchoString function below returns a string or null. 170 the EchoString function below returns a string or null.
152 171
153 ```javascript 172 ```javascript
154 interface EchoService { 173 interface EchoService {
155 EchoString(string? value) => (string? value); 174 EchoString(string? value) => (string? value);
156 }; 175 };
157 ``` 176 ```
158 177
159 The response is delivered to the function caller asynchronously. In C++ the 178 The response is delivered to the function caller asynchronously. In C++ the
160 caller provides a Callback object whose Run() method has one argument for 179 caller provides a Callback object whose Run() method has one argument for
161 each response parameter. In JS, Mojo functions that specify a response return 180 each response parameter. In JS, Mojo functions that specify a response return
162 a Promise object. The Promise resolves to an object with one property per 181 a Promise object. The Promise resolves to an object with one property per
163 response parameter. In the EchoString case that would be something like 182 response parameter. In the EchoString case that would be something like
164 {value: "foo"}. 183 `{value: "foo"}`.
165 184
166 Similarly, the implementation of a Mojo interface functions that specify a 185 Similarly, the implementation of a Mojo interface functions that specify a
167 response, must return a Promise. The implementation of EchoString() could 186 response, must return a Promise. The implementation of EchoString() could
168 be written like this: 187 be written like this:
169 188
170 ```javascript 189 ```javascript
171 MyEchoStringImpl.prototype.EchoString = function(s) { 190 MyEchoStringImpl.prototype.EchoString = function(s) {
172 return Promise.resolve({value: s}); 191 return Promise.resolve({value: s});
173 }; 192 };
174 ``` 193 ```
175 194
176 - Applications can request and provide services 195 ## Requesting and Providing Services
196
197 Mojo applications can connect to services provided by other applications and
198 they can provide services of their own. A service is an implementation of a Mojo
199 interface that was defined as part of a Mojo module in a ".mojom" file.
177 200
178 When an application starts, its initialize() method runs and then its 201 When an application starts, its initialize() method runs and then its
179 acceptConnection() method runs. The acceptConnection() method 202 acceptConnection() method runs. The acceptConnection() method
180 indicates that another application has connected to this one and it 203 indicates that another application has connected to this one and it
181 always runs at least once. 204 always runs at least once.
182 205
183 ```javascript 206 ```javascript
184 acceptConnection(initiatorURL, serviceProvider) { 207 acceptConnection(initiatorURL, serviceProvider) {
185 // provide services to the initiator here 208 // provide services to the initiator here
186 // request services from the initiator here 209 // request services from the initiator here
(...skipping 30 matching lines...) Expand all
217 240
218 The usage examples that follow are based on the following trivial Mojo 241 The usage examples that follow are based on the following trivial Mojo
219 interface: 242 interface:
220 243
221 ```javascript 244 ```javascript
222 interface EchoService { 245 interface EchoService {
223 EchoString(string? value) => (string? value); 246 EchoString(string? value) => (string? value);
224 }; 247 };
225 ``` 248 ```
226 249
227 -- Requesting a service using the Application's Shell 250 ### Requesting a Service Using the Application's Shell
228 251
229 Given the URL of a Mojo application that implements the EchoService we 252 Given the URL of a Mojo application that implements the EchoService we
230 can use the application's shell to get an EchoService proxy. Here's a 253 can use the application's shell to get an EchoService proxy. Here's a
231 complete application: 254 complete application:
232 255
233 ```javascript 256 ```javascript
234 #!mojo:js_content_handler 257 #!mojo:js_content_handler
235 258
236 define("main", [ 259 define("main", [
237 "console", 260 "console",
238 "mojo/services/public/js/application", 261 "mojo/services/public/js/application",
239 "services/js/test/echo_service.mojom" 262 "services/js/test/echo_service.mojom"
240 ], function(console, appModule, echoModule) { 263 ], function(console, appModule, echoModule) {
241 264
242 class EchoShellRequest extends appModule.Application { 265 class EchoShellRequest extends appModule.Application {
243 initialize(args) { 266 initialize(args) {
244 var url = "file:/foo/bar/echo.js"; 267 var url = "file:/foo/bar/echo.js";
245 var echoService = this.shell.connectToService(url, echoModule.EchoService) ; 268 var echoService = this.shell.connectToService(url, echoModule.EchoService) ;
246 echoService.echoString("foo").then(function(result) { 269 echoService.echoString("foo").then(function(result) {
247 console.log("echoString(foo) => " + result.value); 270 console.log("echoString(foo) => " + result.value);
248 }); 271 });
249 } 272 }
250 } 273 }
251 return EchoShellRequest; 274 return EchoShellRequest;
252 }); 275 });
253 ``` 276 ```
254 277
255 278
256 -- Providing a service 279 ### Providing a Service
257 280
258 A complete application that unconditionally provides the EchoService 281 A complete application that unconditionally provides the EchoService
259 looks like this: 282 looks like this:
260 283
261 ```javascript 284 ```javascript
262 #!mojo:js_content_handler 285 #!mojo:js_content_handler
263 286
264 define("main", [ 287 define("main", [
265 "mojo/services/public/js/application", 288 "mojo/services/public/js/application",
266 "services/js/test/echo_service.mojom" 289 "services/js/test/echo_service.mojom"
(...skipping 18 matching lines...) Expand all
285 interface. If the EchoService defined a client interface, the factory 308 interface. If the EchoService defined a client interface, the factory
286 function's client parameter would be a proxy for the initiator's 309 function's client parameter would be a proxy for the initiator's
287 client service. EchoService doesn't have a client so we could have 310 client service. EchoService doesn't have a client so we could have
288 omitted this parameter. 311 omitted this parameter.
289 312
290 Each time another application connects to this one, the EchoServiceImpl 313 Each time another application connects to this one, the EchoServiceImpl
291 function will be called. The caller will be able to run the 314 function will be called. The caller will be able to run the
292 echoString() method and will get its response via a Promise. 315 echoString() method and will get its response via a Promise.
293 316
294 317
295 -- Final note 318 ## Final note
296 319
297 An initiator's serviceProvider object can be retained and used to 320 An initiator's serviceProvider object can be retained and used to
298 request or provide services at any time, not just from within 321 request or provide services at any time, not just from within
299 application's acceptConnection() method. 322 application's acceptConnection() method.
300 323
301 324
302 --- Interface Parameters --- 325 # Interface Parameters
303 326
304 The caller and callee use cases that follow are in terms of the following mojom : 327 The caller and callee use cases that follow are in terms of the following mojom :
305 328
306 ``` 329 ```
307 [Client=Bar] 330 [Client=Bar]
308 interface Foo { 331 interface Foo {
309 } 332 }
310 333
311 [Client=Foo] // Redundant but always implicitly true. 334 [Client=Foo] // Redundant but always implicitly true.
312 interface Bar { 335 interface Bar {
313 } 336 }
314 337
315 interface I { 338 interface I {
316 provideFoo(Foo foo); 339 provideFoo(Foo foo);
317 requestFoo(Foo& foo); // effectively: provideFoo(Bar bar) 340 requestFoo(Foo& foo); // effectively: provideFoo(Bar bar)
318 } 341 }
319 ``` 342 ```
320 343
321 -- In General 344 ## Stubs and Proxies
345
346 TODO: briefly introduce message pipes.
347 TODO: explain what stubs and proxies are, explain what's meant by "local" and "r emote".
348 TODO: explain the StubBindings and ProxyBindings functions.
349 TODO: support creating a proxy from a handle new MyProxy(someHandle);
350 TODO: explain the Connection object and how it relates to this stuff.
322 351
323 From a user's point of view, the bindings are in terms of the (remote) 352 From a user's point of view, the bindings are in terms of the (remote)
324 proxy class and the (local) stub class's implementation delegate 353 proxy class and the (local) stub class. Properties are added to instances
325 (internally, that's the stub class's delegate$ property). The 354 of these classes using functions called StubBindings and ProxyBindings.
326 bindings will add/use a local$ property on proxy objects which points
327 to the stub class's implementation delegate. They also manage remote$
328 property on the implementation delegate whose value is the proxy.
329
330 All that implies:
331
332 fooImpl.remote$.local$ == fooImpl (the stub class's delegate)
333 fooProxy.local$.remote$ == fooProxy
334 355
335 356
336 -- Callers 357
358 ## Callers
337 359
338 Assuming that we have a proxy for interface I, iProxy. 360 Assuming that we have a proxy for interface I, iProxy.
339 361
340 An iProxy.provideFoo() call implies that we have an implementation of 362 An iProxy.provideFoo() call implies that we have an implementation of
341 Foo, and want a proxy for Bar (Foo's client). 363 Foo, and want a proxy for Bar (Foo's client).
342 364
343 ```javascript 365 ```javascript
344 var myFooImpl; 366 var barProxy;
345 provideFoo(myFooImpl); 367 iProxy.provideFoo(function(remote) {
346 myFooImpl.remote$; // A Bar proxy initialized by provideFoo(), undefined if Foo has no client. 368 barProxy = remote;
369 return myFooImpl;
370 });
347 ``` 371 ```
348 372
349 An iProxy.requestFoo() call implies that we have an implementation of 373 An iProxy.requestFoo() call implies that we have an implementation of
350 Bar and want a proxy for Foo (Bar's client). 374 Bar and want a proxy for Foo (Bar's client).
351 375
352 ```javascript 376 ```javascript
353 var myBarImpl; // If Foo has no client then this is just {}. 377 var fooProxy;
354 requestFoo(myBarImpl); 378 iProxy.requestFoo(function(remote) {
355 myBarImpl.remote$; // A Foo proxy initialized by requestFoo. 379 fooProxy = remote;
380 return myBarImpl;
381 });
356 ``` 382 ```
357 383
384 In the requestFoo() case, if no client were defined for Bar the function
385 parameter need not return anything.
386
358 The wget.js example includes a request for the URLLoader service. 387 The wget.js example includes a request for the URLLoader service.
359 388
360 -- Callees 389 ## Callees
361 390
362 An implementation of provideFoo(Foo foo) implies that we have an 391 An implementation of provideFoo(Foo foo) implies that we have an
363 implementation of Bar (Foo's client) and want a proxy to the Foo 392 implementation of Bar (Foo's client) and want a proxy to the Foo
364 that has been passed to us. 393 that has been passed to us.
365 394
366 ```javascript 395 ```javascript
367 void provideFoo(fooProxy) { 396 void provideFoo(fooProxy) {
368 fooProxy.local$ = myBarImpl; // sets myFooImpl.remote$ = fooProxy 397 ProxyBindings(fooProxy).setLocalDelegate(myMyBarImpl);
369 } 398 }
370 ``` 399 ```
371 400
372 An implementation of requestFoo(Foo& foo) implies that we have an 401 An implementation of requestFoo(Foo& foo) implies that we have an
373 implementation of Foo and want a proxy for the Bar (Foo's client) 402 implementation of Foo and want a proxy for the Bar (Foo's client)
374 that's been passed to us. 403 that's been passed to us.
375 404
376 ```javascript 405 ```javascript
377 void requestFoo(barProxy) { 406 void requestFoo(barProxy) {
378 barProxy.local$ = myFooImpl; // sets myFooImpl.remote$ = barProxy 407 ProxyBindings(barProxy).setLocallocalDelegate(myFooImpl);
379 } 408 }
380 ``` 409 ```
381
OLDNEW
« no previous file with comments | « examples/js/README.md ('k') | examples/js/wget.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698