JavaScript as a Protocol for Native Development

Alex R. Young





essays native

JavaScript as a Protocol for Native Development

Posted by Alex R. Young on .

essays native

JavaScript as a Protocol for Native Development

Posted by Alex R. Young on .

This is a guest post by Jonathan Gros-Dubois.

These days it's hard to find a platform that can't run JavaScript - it runs in browsers, on servers (Node.js), on mobile devices (iOS, Android), TVs, drones, robots, and IoT devices. It can also be embedded inside many other popular programming languages, thanks to the JavaScript interfaces/VMs they provide. The proliferation of JavaScript runtimes makes me wonder: could JavaScript become a universal language for cross-platform, cross-device communication? Can it free us from an over-dependence on restrictive communication protocols?

If someone wants to write a custom server, which uses its own protocol or adds a layer on top of an existing protocol, they will typically write a human-readable RFC protocol specification to accompany it. Later, people can read the specification and start implementing clients for it. Usually, the people who built the server will also implement and maintain one or more 'official' clients.

Overall, the current approach works, but it has some significant drawbacks:

  • Behaviour is often inconsistent between clients. Bugs and vulnerabilities may also diverge.
  • Due to duplication of source code (across different languages), it's difficult to maintain the repositories for all of these clients. As a result, they become quickly outdated.
  • It makes it difficult for the client-server ecosystem to evolve as a whole because you're limited by the length/complexity of your RFC specification. The more features your client has, the longer your RFC has to be and the harder it is to implement/maintain across multiple platforms/languages.

As an example, the Socket.io project has published its own RFC protocol specification and this specification has formed the the basis for at least 5 different clients (note that these clients have essentially no code reuse between them):

This is the current convention for doing things and it has become a bottleneck in client-server innovation. There may be a simpler, less conventional alternative to consider:
don't write an RFC! Or to put it differently: let JavaScript code act as your specification! Thanks to recent advances, most custom, (high-level) protocols can now simply be hardcoded in JavaScript on top of WebSockets. You no longer have to write-up a lengthy specification before implementing multiple versions of (what should be) the same client. You can just write it once in JavaScript and embed it inside various JavaScript VMs (for whatever language/platform you want to support) - then you just expose the JavaScript functionality through a lightweight native interface. It's very easy to keep all your clients up to date - It’s typically just a matter of importing your updated client (.js) file and recompiling your project.

This idea occurred to us while working on SocketCluster. It started when my colleague (Lihan Li) and I decided to put together a native iOS client for SC. Our community was quite small and our existing JavaScript client was quite feature-rich, so it was clear that implementing a native Objective-C client from scratch was not an option (or at least it would have to be a severely trimmed-down version of the JS client).

We wanted to keep a lot of the 'nice to have' behaviours which the JS client provided (like auto-reconnect, pub/sub, auto-resubscribe, JWT auth token management, etc...). These behaviours would be difficult to describe as a protocol (would require a lengthy RFC specification), but we really wanted them to be available natively on iOS.

We looked at using JavaScriptCore as our JavaScript VM first because it seemed lightweight: it's built into iOS. Due to various issues and restrictions (some of which may be our own fault), we decided to use an invisible WebView as our VM instead.

The WebView approach worked out surprisingly well. We just had to declare a simple Objective-C interface with a matching JavaScript 'bridge' interface to allow calling various internal JavaScript methods from outside the VM (using native Objective-C code). The result is that we were able to create a full-featured, highly maintainable native iOS client after less than 2 weekend's worth of work! (see Resources section at the bottom of this article for the source code and the iOS-to-JavaScript bridge we used). Note that because we are not using any rendering features of the WebView, performance is not an issue.

The 'wrapper' code for the client is less than 250 lines of Objective-C and 150 lines of JavaScript in total (which is just simple binding logic) but the best part of this approach is that keeping our official client up to date is really easy.

Keep an eye out for our android client - it's coming soon.

Special thanks to OpenLearning for their feedback and support in this highly adventurous project.


Research and development was by Lihan Li with assistance from Jonathan Gros-Dubois.