JavaScript Mojo Example Applications
=====================

hello.js, world.js - A minimal application that connects to another.

wget.js - Uses the network service to load a URL.

cube.js - A JS version of examples/sample_app.

--- Running Mojo Applications --- 

A Mojo application written in JavaScript is launched with mojo_shell like this:

  mojo_shell <js-application-url>

Where js-application-url is a URL understood by the shell. For example
a file or an http URL that names a JS source file. The JS file itself
must begin with a Mojo "shebang" that specifies the Mojo URL of the JS
content handler. In other words, the first line of the JS source file
must be:

  #!mojo:js_content_handler

Following the shebang should be a single AMD module called "main" whose value
is an Application subclass. The JS content handler will create an instance of
the Application and make it the client of the Mojo shell. The JS content handler
is itself a Mojo application and it's responsible for creating an instance of V8
and loading the "main" JS module and all of the modules the main module
depends on. 

This is the overall structure of a JS Mojo application:

  #!mojo:js_content_handler

  define("main", ["mojo/services/public/js/application", 
    <list of other modules that this application depends on>
],
    function(appModule, <one parameter per dependent module>) {
      class MyApplication extends appModule.Application {
        constructor(appShell, url) {
          super(appShell, url); // Initializes this.shell, this.url.
          // MyApplication initializations here. 
        }

        initialize(args) {
        }

        acceptConnection(url, serviceProvider) {
        }
      }

      return MyApplication;
    });

The hello.js example is little more than this basic skeleton.

The JS content handler loads the "main" module and makes an instance of its
value, which must be an Application subclass. The application's constructor is 
passed two arguments:

appShell - a pointer to the Mojo shell. Typically this will be wrapped by a
    Shell object, see below.

url - the URL this application was loaded from as a String.

The (inherited) Application class constructor initializes the shell and url
properties. It's unlikely that you'll want to use the appShell argument
directly.

The initialize() and acceptConnection() methods are defined by application.mojom
and they're needed because the JS content handler makes the JS application the
Mojo shell's client.


--- JavaScript Classes --- 

The JS content handler depends on the ECMAScript6 ("Harmony") classes feature.



--- Mojo Application Structure --- 

Mojo applications can connect to services provided by other applications and
they can provide services of their own. A service is an implementation of a Mojo
interface that was defined as part of a Mojo module in a ".mojom" file.

To implement a service you'll need the JS "bindings" for the Mojo interface. The
bindings are generated by the build system and end up in files whose name is the
same as the '.mojom' file with a '.js' suffix. It's often helpful to look at the
generated 'mojom.js' files.

The JS Shell class simplifies connecting to applications and services. It's a
wrapper for the Application's appShell argument. The Application constructor
creates a Shell and assigns it to |this.shell|.

The Shell's connectToService() method returns a "proxy" to a service provided by
another application.

The JS bindings for a Mojo interface's API are delivered as a JS module whose
name is based on the '.mojom' file's path. For example, to use the Mojo network
service you need the JS module based on network_service.mojom:

  define("main", [
    "mojo/services/network/public/interfaces/network_service.mojom",
    "mojo/services/public/js/application",
  ]
    function(netModule, appModule) {
      class MyApplication extends appModule.Application {
        initialize(args) {
          var netService = this.shell.connectToService(
              "mojo:network_service", netModule.NetworkService);
          // Use netService's NetworkService methods.
        }
        ...
      }

      return MyApplication;
    });

The first connectToService() parameter is the Mojo URL for the network service
application and the second is the JS "interface" object for NetworkService. The
JS interface object's properties identify the (generated) JS bindings classes
used to provide or connect to a service. For example (from
network_service.mojom.js):

  var NetworkService = {
    name: 'mojo::NetworkService', // Fully qualified Mojo interface name.
    proxyClass: NetworkServiceProxy,
    stubClass: NetworkServiceStub,
    // ...
  };

The 'proxyClass' is used to access another application's NetworkService and the
'stubClass' is used to create an implementation of NetworkService. 

In the netService case above the Shell connects to the Mojo application at
"mojo:network_service", then connects to its service called 
'NetworkService.name' with an instance of 'NetworkService.proxyClass'. The proxy
instance is returned. The netService proxy can be used immediately.


--- Interface Parameters --- 

Mojo functions with interface valued parameters allow one to request a service
from a service or to provide a service to a service. The
indirect_service example demonstrates this.

The NetworkService CreateURLLoader() method has an interface request parameter:

  interface NetworkService {
    // Connect the loader parameter to a URLLoader service.
    CreateURLLoader(URLLoader& loader);
    ...
  }

Interface request parameters can be specified as an instance of the interface's
proxy class. Ordinary interface parameters can be specified as an instance of
the interface's stub class. The stub class constructor has an optional delegate
parameter that defines the stub's implementation.

Here's an example of an interface request parameter taken from wget.js:

  var urlLoader = new loader.URLLoader.proxyClass;
  netService.createURLLoader(urlLoader); // interface& parameter

  var urlRequest = new loader.URLRequest({
    url: "http://www.cnn.com",
    method: "GET",
    auto_follow_redirects: true
  });

  urlLoader.start(urlRequest).then(function(result) {
      // ..Do something with result.response
  });


--- Mojo Responses are Promises --- 

Mojo functions can return zero or more values called a "response". For example
the EchoString function below returns a string or null.

interface EchoService {
  EchoString(string? value) => (string? value);
};

The response is delivered to the function caller asynchronously. In C++ the 
caller provides a Callback object whose Run() method has one argument for
each response parameter. In JS, Mojo functions that specify a response return
a Promise object. The Promise resolves to an object with one property per
response parameter. In the EchoString case that would be something like 
{value: "foo"}.

Similarly, the implementation of a Mojo interface functions that specify a
response, must return a Promise. The implementation of EchoString() could
be written like this:

  MyEchoStringImpl.prototype.EchoString = function(s) {
    return Promise.resolve({value: s});
  };
